Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

binding a function passed to a component

Tags:

react-native

Reading this SO answer, I understand that when I pass a function to a react component, I have to bind a function in the constructor like this

 constructor(props) {
    super(props);

    //binding function
    this.renderRow = this.renderRow.bind(this);
    this.callThisFunction = this.callThisFunction.bind(this);
    }

or I'll get an error like this.

null is not an object: evaluating this4.functionName

Following that advice, I bound the function in the constructor but I'm still getting the same error.

I'm making a Master/Detail app with React Native based on the Movies example in the react native repo, except that I don't use this syntax

var SearchScreen = React.createClass({

(which is what the repo is) but rather this ES6 style syntax

class ListOfLists extends Component {

In my list view, I render a row like this.

  class MovieList extends Component{
      constructor(props){
        super(props);
        this.selectMovie = this.selectMovie.bind(this);
        this.state = {
          dataSource: new ListView.DataSource({
            rowHasChanged: (row1, row2) => row1 !== row2,
          }),
        };
      }
          renderRow(
            movie: Object,
            sectionID: number | string,
            rowID: number | string,
            highlightRowFunc: (sectionID: ?number | string, rowID: ?number | string) => void,
          ) {
          console.log(movie, "in render row", sectionID, rowID);
            return (
              <ListCell 
                onSelect={() => this.selectMovie(movie)}
                onHighlight={() => highlightRowFunc(sectionID, rowID)}
                onUnhighlight={() => highlightRowFunc(null, null)}
                movie={movie}
              />
            );
          }

       selectMovie(movie: Object) {
        if (Platform.OS === 'ios') {
          this.props.navigator.push({
            title: movie.name,
            component: TodoListScreen,
            passProps: {movie},
          });
        } else {
          dismissKeyboard();
          this.props.navigator.push({
            title: movie.title,
            name: 'movie',
            movie: movie,
          });
        }
      }
     render(){
        var content = this.state.dataSource.getRowCount() === 0 ?
            <NoMovies  /> :
            <ListView
             ref="listview"
             renderSeparator={this.renderSeparator}
             dataSource={this.state.dataSource}
             renderFooter={this.renderFooter}
             renderRow={this.renderRow} 
             automaticallyAdjustContentInsets={false}
             keyboardDismissMode="on-drag"
             keyboardShouldPersistTaps={true}
             showsVerticalScrollIndicator={false}
             renderRow={this.renderRow}
     }

The key line is this.selectMovie(movie). When I click a row with a movie name, I get an error

null is not an object: evaluating this4.selectMovie

Question: why is it telling me null is not an object or rather why is that function null?

Update:

I added the render method to the code to show where renderRow is getting used

like image 738
Leahcim Avatar asked Feb 17 '16 01:02

Leahcim


1 Answers

Way to deal with this problem without modifying your code a lot is adding this.renderRow = this.renderRow.bind(this) to your class constructor.

class New extends Component{   
  constructor(){
    this.renderRow = this.renderRow.bind(this)
  }

  render(){...} 
}

you have add the property renderRow = { this.renderRow },In fact the renderRow executed with binded to null object.Try to console this in renderRow you will find it is GlobalObject instead of Class MovieList which you desire to.

like image 107
Oboo Cheng Avatar answered Oct 02 '22 14:10

Oboo Cheng