beck
beck

Reputation: 3027

this.props gives undefined while using redux

I am new to redux. I've passed a value through mapStateToProps and this.props has value inside render(). However, if I console this.props in function like in renderRow function in the following example, it gives undefined. Why is this the case?

constructor() {
    super();
}

renderRow(rowData) {
    //this.console gives undefined why
    console.log('props1', this.props);
}

render() {
    //this.props has value here
    {console.log('props1', this.props)}
    return (
      <View style={styles.container}>

        <ListView
            dataSource={this.dataSource}
            renderRow={this.renderRow}
        />

      </View>
    ); 
}

const mapStateToProps = state => {
    return {selectionsList: state.selections, 
            selectionId: state.selectionId};
}

Upvotes: 0

Views: 45

Answers (1)

Bloomca
Bloomca

Reputation: 1794

The reason for that is that you pass a function to another component, and this function has no binding to your class instance anymore. It has it only if you call it (not pass) with actual object on the left – you can read more in my article about this. You have several solutions here, and you can read about them in docs about event handling. It is a common pattern when adding an event handler.

So, you can do the following:

  1. use class properties:

    renderRow = (rowData) => { console.log('props1', this.props); }

If you use it this way, it will automatically bind your function to your instance.

  1. just create a new arrow function when you pass the callback:

    <ListView
        dataSource={this.dataSource}
        renderRow={(data) => this.renderRow(data)}
    />
    

Arrow functions don't have their own this, so it will work correctly.

  1. You can bind your method when you pass it as a property. It works almost the same way as the previous one – every time we render, we create a new function:

    <ListView
        dataSource={this.dataSource}
        renderRow={this.renderRow.bind(this)}
    />
    
  2. Bind in constructor. You can just bind it in constructor – it will create a new function when instantiating, so you won't do it every re-render. It works sort of similar to the first one, but is more explicit (and much more verbose):

    constructor(props) {
      super(props);
    
      this.renderRow = this._renderRow.bind(this);
    }
    
    _renderRow(data) {
       console.log('props1', this.props);
    }
    

I personally would say just use the first approach, it is very common and stable enough (it is stage 3 in proposals).

Upvotes: 1

Related Questions