Utkarsh Sah
Utkarsh Sah

Reputation: 301

How to get Element Properties in React Native on a Click Event

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

Answers (5)

PrashanD
PrashanD

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

Florent Roques
Florent Roques

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)

ref: React Handling Events

(credits to https://stackoverflow.com/a/42125039/1152843)

Upvotes: 1

alexandros84
alexandros84

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

Utkarsh Sah
Utkarsh Sah

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

Kawatare267
Kawatare267

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

Related Questions