Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read props from a React Native touchable event currentTarget?

Tags:

react-native

I have the following React Native code that runs the press() method when a user taps an image. I want to get the itemIndex prop from the event object. I set a break point in the press method and added some expressions to the Watch. From the Watch I determined that the target (event origination) from the event is the Image which is correct. The itemIndex prop is also available. The element being processed is the currentTarget, the Watch sees it's a "RCTView" and I was expecting a TouchableOpacity, so maybe underneath TouchableOpacity is a View? The currentTarget itemIndex prop is undefined, why? How can I get the props from the currentTarget?

I want to do it this way to avoid creating addition methods for each rendered item.

FYI, ref={(c) => this._input = c} will not work because it's being run in a loop. onPress={(e) => this.press(e, i)} creates a new function which I'm trying to avoid.

Watch

  1. target._currentElement.props.itemIndex: 2
  2. target._currentElement.type.displayName: "RCTImageView"
  3. currentTarget._currentElement.props.itemIndex: undefined
  4. currentTarget._currentElement.type.displayName: "RCTView"

    press: function(event){
        var currentTarget = ReactNativeComponentTree.getInstanceFromNode(event.currentTarget);
        var target = ReactNativeComponentTree.getInstanceFromNode(event.target);
        var currentTargetIndex = currentTarget._currentElement.props.itemIndex;
        var targetIndex = target._currentElement.props.itemIndex;
        var url = this.state.data.items[currentTargetIndex].url;
        Linking.openURL(url).catch(err => console.error('An error occurred', err));
    },
    
    render: function() {
    return (
        <ScrollView horizontal={true} showsHorizontalScrollIndicator={false} style={styles.galleryView}>
            {
                this.state.data.items.map((data, i) =>
                    <TouchableOpacity itemIndex={i} key={i} activeOpacity={0.5} onPress={this.press} >
                        <Image itemIndex={i} key={i} source={{uri:data.previewImageUri}} style={styles.galleryImage} />
                    </TouchableOpacity>
                )
            }
        </ScrollView>
    );
    }
    
like image 725
Andy Root Avatar asked Oct 30 '22 12:10

Andy Root


2 Answers

I actually came across this same issue recently, I found two different ways you could approach this. The easier way of doing it is altering your onPress to pass an index to your press function, this is the 2nd way of doing it:

press: function(event, index){
  var url = this.state.data.items[index].url;
  Linking.openURL(url).catch(err => console.error('An error occurred', err));
},

render: function() {
  return (
    <ScrollView
      horizontal={true}
      showsHorizontalScrollIndicator={false}
      style={styles.galleryView}
    >
    {
      this.state.data.items.map((data, i) =>
        <Images data={data} key={i} index={i} press={this.press} />
      )
    }
    </ScrollView>
    );
}

const Images = (props) => {
  const imageClicked = (e) => {
    props.press(e, props.index);
  }
  return (
    <TouchableOpacity activeOpacity={0.5} onPress={imageClicked} >
      <Image source={{uri:props.data.previewImageUri}} style={styles.galleryImage} />
    </TouchableOpacity>
  )
}
like image 61
Matt Aft Avatar answered Nov 03 '22 00:11

Matt Aft


You could make your event handler a curried function that accepts extra parameters.

 //Curried function for onPress event handler
  handleOnPress = (someId, someProp) => event => {
    //USE someProp ABOVE TO ACCESS PASSED PROP, WHICH WOULD BE undefined IN THIS CASE
    //Use event parameter above to access event object if you need
    console.log(someProp)

    this.setState({
      touchedId: someId
    })
  }

Checkout the working snack below

https://snack.expo.io/@prashand/accessing-props-from-react-native-touch-event

like image 29
PrashanD Avatar answered Nov 02 '22 22:11

PrashanD