1

I am trying to attach a method to take in the data passed into a ListView. Specifically, I am utilizing the ListView React Native component and it's _renderRow function that maps a dataSource to different rows. Within the datasource, I would like to pass in one of the data elements as an argument to this method:

class MainComponent extends Component {
    constructor(props) {
      super(props)
      var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
      this.state = { dataSource: ds.cloneWithRows([['foo1', 'bar1'], ['foo2','bar2']])};
      this._renderRow = this._renderRow.bind(this);
    }
    render() {
       return (
           <View>
             <ListView
               dataSource={this.state.dataSource} // [['foo1', 'bar1'], ['foo2', 'bar2']]
               renderRow={this._renderRow}
             />
           </View>
         );
    }
    _renderRow(rowData) {
      return (
         <SomeComponent onPress={_ => this.someMethod} data={rowData} /> 
         //Trying to call someMethod with argument 'bar1'.
         //I have also tried passing in the argument here with:
         // onPress={_ => this.someMethod({rowData[1]})}
       )
    }
    someMethod(data) {
      //do something with data
    }
}

class SomeComponent extends Component {
    render() {
      return (
         <TouchableHighlight
         underlayColor='#EFEFEF'
         onPress={this.props.onPress(this.props.data[1])}>
         //Is this the correct way to pass in 'bar1' into the method?
           <View>
             <Text>{this.props.data[0]}</Text>
           </View>
         </TouchableHighlight>
      )
   }
 }

So, what is the correct way to do this? I imagine that it should be fairly common to want to pass in the DataSource data to the onPress method, but I wasn't able to find anything online.

Thanks!

txizzle
  • 820
  • 7
  • 19

2 Answers2

0

In your onPress in the render row simply do:

onPress={this.someMethod}

That should do the trick.

rmevans9
  • 5,472
  • 1
  • 21
  • 18
  • Thanks for the response. Issue is that that would cause someMethod to be called immediately upon render, which is why I opted to go with the arrow function: http://stackoverflow.com/questions/34226076/why-is-my-onclick-being-called-on-render-react-js Alternatively, I tried to do onPress={_ => this.someMethod(rowData[2])}, but that's incorrect notation it seems. I'm confident that there has to be an easy way to do something like this – txizzle Jul 19 '16 at 15:16
  • Actually no it won't. So long as you leave off the () when putting it in. I do this all the time and here is a example showing it won't call it immediately: https://rnplay.org/apps/_9C0Cw – rmevans9 Jul 19 '16 at 15:23
  • Oh yep, you are completely correct - without the () the function is not called upon render. The issue for my case was actually passing in arguments. Without the () in the onPress, I was unable to pass in data within the SomeComponent. Basically when I pass in `onPress={this.someMethod}` as a prop, and then within the actual SomeComponent I do `onPress={this.props.onPress(this.props.data[1])}`, React tells me that `this.props.data[1]` is `nil`. Any idea why? Alternatively, see my answer as a solution, but I am curious as to why this approach wouldn't work. – txizzle Jul 19 '16 at 15:41
  • I would recommend checking the value of this.props to ensure data is what you expect it to be. I personally have not passed an array of arrays via a listview in React Native so I can't confirm if that is causing issues. I would suspect that it wouldn't but never know till you try. What if instead of passing an array of arrays you pass an array of objects and reference the value directly instead? Does that still return null? – rmevans9 Jul 19 '16 at 16:34
  • When I was debugging yesterday, this.props did have the expected value. However, I think that the issue is that when you pass in the callback like `onPress={this.someMethod}`, React Native expects `someMethod` to take in 0 arguments. That's why arrow notation with an argument was needed on the high-level callback to ensure that parameters could be passed in (instead of being ignored/set to nil). That seem like a reasonable explanation? – txizzle Jul 19 '16 at 19:14
0

Turns out that this solution applies: React-Native ListView renderRow issues passing props. The right way or the wrong way

If your high-level callbacks accept a parameter, you need to make sure your anonymous functions accept a parameter as well (Note: creating anonymous functions using the arrow syntax automatically binds our function to the value of this in the current context)

In the _renderRow function, I need to attach arguments in the signature of the function (someMethod) that is being passed down as a prop. I do this by just adding an argument through arrow notation:

_renderRow(rowData) {
  return (
     <SomeComponent onPress={(args) => this.someMethod(args)} data={rowData} />
   )
}

In SomeComponent's onPress, I am then able to actually call the onPress method with an argument:

render() {
  return (
     <TouchableHighlight
     underlayColor='#EFEFEF'
     onPress={() => this.props.onPress(this.props.data[1])}>
       <View>
         <Text>{this.props.data[0]}</Text>
       </View>
     </TouchableHighlight>
  )
Community
  • 1
  • 1
txizzle
  • 820
  • 7
  • 19