I am experiencing a strange issue in React. I think probably I have not fully grasped how React works and I really appreciate your help.
Please find below my React component:
class myComponent extends Component {
state = {
value: ''
}
updateValue = e => {
this.setState({
value: e.target.value
})
}
render() {
return (
<form>
<input type="text" onChange={this.updateValue} defaultValue={this.state.value} />
</form>
)
}
}
Then, now if I type something in the text field, I will get following warning and errors:
Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property target
on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist().
Uncaught TypeError: Cannot read property 'value' of null
But if I change the 'updateValue' method to:
updateValue = e => {
const newValue = e.target.value
this.setState({
value: newValue
})
}
It will work without any issue.
Updated answer
As @FelixKling pointed out, my answer wasn't entirely correct. My answer is only valid if you pass a function as a parameter to setState
, not if you pass an object like done in the question.
If you pass an object to setState
, the parameter will be evaluated immediately, that is, before the event has been nullified. As such, the mentioned error won't occur.
If you pass a function to setState
, the parameter will be evaluated within that function, which happens after updateValue
has completed/returned and the event has been nullified. If you pass a function to setState
, you must store the e.target.value
in a variable (or call e.persist()
) before setState
.
Old (slightly wrong) answer
This problem occurs because (as the error message says) the event is set to null when the callback (your updateValue
function) is completed.
Because this.setState()
is an asynchronous function, it will not be executed immediately. As a result, this.setState()
is actually executed after your updateValue
is finished, and hence after the event has been nullified.
Your solution is actually the proposed way from the React docs!
The SyntheticEvent is pooled. This means that the SyntheticEvent object will be reused and all properties will be nullified after the event callback has been invoked. This is for performance reasons. As such, you cannot access the event in an asynchronous way.
Basically, the click event (e
) is not accessible inside the asynchronous setState()
due to React's Event Pooling, unless you use event.persist()
(as mentioned in the warning you received).
React Event Pooling: https://reactjs.org/docs/events.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With