Reputation: 301
How should I access the properties of an element without using the 'this' keyword in React Native? I have a function with which the parent class itself is bound as 'this' but I want to access the properties of the element that is being clicked. Here's the code-
import {Circle} from 'react-native-svg';
export default App extends Component {
constructor(props) {
super(props);
this.state = {activeX: null}
}
handleTouch(event) {
const x = event.target.cx; //How to access "cx" property here?
this.setState({ activeX: x });
}
render() {
return (
<Circle cx='10' cy='10' r='5' onPress={this.handleTouch.bind(this)}/>
<Circle cx='20' cy='20' r='5' onPress={this.handleTouch.bind(this)}/>
);
}
}
Upvotes: 8
Views: 12097
Reputation: 2764
You can change your event handler to a curried function like so:
import {Circle} from 'react-native-svg';
export default App extends Component {
constructor(props) {
super(props);
this.state = {activeX: null}
}
//Use ES6 arrow and avoid this.bind
//Curried function handleTouch accepts cx, cy as extra parameters
handleTouch = (cx, cy) => event => {
console.log(cx, cy) // This is how you access props passed to Circle here
console.log(event)
this.setState({ activeX: cx });
}
render() {
//You are actually invoking the handleTouch function here, whose return value is
//a function, which is set as the onPress event handler for the <Circle> component
return (
<Circle cx='10' cy='10' r='5' onPress={this.handleTouch(10, 10)}/>
<Circle cx='20' cy='20' r='5' onPress={this.handleTouch.(20, 20)}/>
);
}
}
Checkout the working snack below:
https://snack.expo.io/@prashand/accessing-props-from-react-native-touch-event
Upvotes: 0
Reputation: 2662
A better way of accessing the component properties in an event is actually by creating a component and passing it the needed data:
import { Circle } from 'react-native-svg';
class TouchableCircle extends React.PureComponent {
constructor(props) {
super(props);
this.circlePressed = this.circlePressed.bind(this);
}
circlePressed(){
this.props.onPress(this.props.cx);
}
render() {
return (
<Circle cx={this.props.cx} cy={this.props.cy} r={this.props.r} onPress={this.circlePressed}/>
);
}
}
export default App extends Component {
constructor(props) {
super(props);
this.state = {activeX: null}
this.handleTouch = this.handleTouch.bind(this);
}
handleTouch(cx) {
this.setState({ activeX: cx });
}
render() {
return (
<TouchableCircle cx='10' cy='10' r='5' onPress={this.handleTouch}/>
<TouchableCircle cx='20' cy='20' r='5' onPress={this.handleTouch}/>
);
}
}
NB: Performance tip from Facebook for event handlers:
We generally recommend binding in the constructor or using the property initializer syntax, to avoid this sort of performance problem. (i.e. to avoid the creation of the callback everytime a component renders)
(credits to https://stackoverflow.com/a/42125039/1152843)
Upvotes: 1
Reputation: 337
Sorry for leaving an answer but I cannot leave a comment since <50 rep.
You should edit the improve part of your answer, with the following bit:
import ReactNativeComponentTree from 'react-native';
instead of what you have right now,
import ReactNativeComponentTree from'react-native/Libraries/Renderer/src/renderers/native/ReactNativeComponentTree';
since is throwing an error (trying to import unknown module).
Upvotes: 1
Reputation: 301
import ReactNativeComponentTree from'react-native/Libraries/Renderer/src/renderers/native/ReactNativeComponentTree';
And access the properties as-
const x = ReactNativeComponentTree.getInstanceFromNode(event.currentTarget)._currentElement.props.cx;
Upvotes: 1
Reputation: 4376
Try this
import {Circle} from 'react-native-svg';
export default App extends Component {
constructor(props) {
super(props);
this.state = {
activeX: null,
cx: 10
}
}
handleTouch = () => {
const x = this.state.cx
this.setState({ activeX: x });
}
render() {
return (
<Circle cx={this.state.cx} cy='10' r='5' onPress={this.handleTouch}/>
);
}
}
Upvotes: 1