Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I access state and props inside event handler

Tags:

reactjs

I have written this code

import React from 'react';
import DimensionPickerAction from '../actions/DimensionPickerActions.js';
import MovieLensAppStore from '../stores/MovieLensAppStore.js';

class DimensionPicker extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            dimensionName: this.props.dimension,
            items: MovieLensAppStore.getAttributes(this.props.dimension),
            currentItem : MovieLensAppStore.getCurrentAttribute(this.props.dimension)
        };
    }

    onSelectionChange(event) {
        console.log(event.target.value)
        DimensionPickerAction.selectionChange(temp.state.dimensionName, event.target.value);
    }

    render() {
        var optionNodes = this.state.items.map((item) => {
            return(<option key={item.id} value={item.val}>{item.val}</option>)
        });
        return(<div><select onChange={this.onSelectionChange} defaultValue={this.state.currentItem}>{optionNodes}</select></div>);
    }

}

export default DimensionPicker;

I can see that when the method onSelectionChange get called both the state and props are null.

I found this thread which discusses the same issue

Access props and state of current component in React JS within an event handler

But the solution does not work for me. I tried to create another method which is then called from onSelectionChange but that method is also not visible to the event handler.

I also tried to store the this pointer in a temp variable ... but that leads to a syntax error.

Does anyone know how to access state and props inside event handler?

like image 201
Knows Not Much Avatar asked Jan 25 '16 04:01

Knows Not Much


1 Answers

As of React .14 event handlers are not being auto-bound to the scope of the component.

You can use the dirty .bind(this) method which I hate and it's slow like so.

render() {
    var optionNodes = this.state.items.map((item) => {
        return(<option key={item.id} value={item.val}>{item.val}</option>)
    });
    return(<div><select onChange={this.onSelectionChange.bind(this)} defaultValue={this.state.currentItem}>{optionNodes}</select></div>);
}

Or use fat arrow functions to wrap the callback in, this is much faster and does not require binding scope since fat arrow function execute on the scope the where created.

render() {
    var optionNodes = this.state.items.map((item) => {
        return(<option key={item.id} value={item.val}>{item.val}</option>)
    });
    return(<div><select onChange={(event) => { this.onSelectionChange(event) }} defaultValue={this.state.currentItem}>{optionNodes}</select></div>);
}
like image 177
Daniel Avatar answered Oct 18 '22 18:10

Daniel