I have been struggling with trying to migrate my React code from ES5 to ES6. As I have found out by now, this
is no longer automatically bound which causes all sorts of hell.
I am trying to figure out by trial and error what objects are being passed around. So far I can find everything and adjust accordingly. However when it comes to this.setState I am having problems because it is not visible in console.log!!!! See screenshot in ES5:
and here is the same kind of code in ES6:
Please teach me how to fish i.e. help me figure out how to understand when an object has this.setState or not?
things i have tried
this
in console so I concluded that setState is still not being bound somehowTo oversimplify how this
works in JS:
instance.foo()
) then this
refers to that object instance.foo()
), then this
is either undefined
or the global object, depending on whether strict mode is in effect.var bar = instance.foo; bar();
.Again, this is an oversimplification; MDN has details.
As this applies to React, and as explained in the React documentation on "Handling Events":
You have to be careful about the meaning of
this
in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget to bindthis.handleClick
and pass it toonClick
,this
will beundefined
when the function is actually called.
In your code, you render your RawInput
as
<RawInput value={this.state.value} updateValue={this.updateValue}/>
You're passing a reference updateValue
function in as a simple function, so this
will not be bound within updateValue
.
Basically, any time you pass a function as a React prop, unless you've bound it yourself, it's likely an error. The symptom is typically that this
is undefined. In your code, it's a little more complicated:
this.props.updateValue(modifiedValue);
The RawInput's updateValue
property is the unbound function App.updateValue
, but because you're invoking it as this.props.updateValue
, it's being called as if it were a method of this.props
- so this
refers to the RawInput's props
. That's why your console.log is showing an object with only two properties (start
and updateValue
): it isn't that setState
isn't bound or went away, it's that updateValue
wasn't bound, so this
isn't what you expect within updateValue
.
To fix the issue, as the React docs explain:
updateValue={(value) => this.updateValue(value)}
updateValue(modifiedValue) {...}
with updateValue = (modifiedValue) => {...}
.updateValue
yourself. For example:constructor(props) {
super(props);
this.updateValue = this.updateValue.bind(this);
}