Skip to content Skip to sidebar Skip to footer

How To Access `this` Inside A Renderrow Of A Listview?

I'm having trouble to run a function for the onPress event inside a row of a ListView. I'm following the React Native tutorial trying to continue from there. It seems it's using ES

Solution 1:

Turns out I found the solution myself, here: https://github.com/goatslacker/alt/issues/283#issuecomment-115391700

The problem is that with ES6 syntax you have no autobinding of this, so you need to do it yourself.

I've learned a bit more since I posted this answer. The real problem is that this is "bound" when the function is executed, not when it's declared. It points to the object the function is attached to when called. For example:

obj.foo(); //inside foo, this points to objbar(); //inside bar, this points to the global object (or undefined in strict mode)

In my example the function this.renderMovie() is passed as a parameter. So inside ListView it will be a "local variable". It will be called "detached" from any object, like the bar() example before, so this will not be what I expect.

It's possible to force the binding of this.

There are 3 possible solutions to my problem, and I like the 3rd one the best:

Option 1: Manually bind this on call

On the code, replace the referece to {this.renderMovie} whith {this.renderMovie.bind(this)}

  render() {
    console.log('this', this); //this is an instance of AwesomeProjectif (!this.state.loaded) {
      returnthis.renderLoadingView();
    }

    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderMovie.bind(this)} //<-- change here
        style={styles.listView}
        />
    );
  }

Option 2: Do the binding on the constructor

And of course, bind the right function:

constructor(props) {
    super(props);
    this.something = this.something.bind(this); // <-- Not this functionthis.renderMovie = this.renderMovie.bind(this); // <-- This function!!this.state = {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
      loaded: false,
    };
  }

Option 3: use the arrow syntax and let them do the job

I like this one the best. You just need to declare the involved function using the arrow syntax so this:

renderMovie(movie) {
    //code here
  }

becomes this:

  renderMovie = (movie) => {
    //code here
  }

Solution 2:

In addition to https://stackoverflow.com/a/36779517/6100821

Option 4: use bind operator

<ListView
    dataSource={this.state.dataSource}
    renderRow={::this.renderMovie} //<-- cleaner, than bind
    style={styles.listView}
    />

Be careful, it's just a proposal, not a standard!

Post a Comment for "How To Access `this` Inside A Renderrow Of A Listview?"