Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue of using e.target.value in React setState function

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.

like image 589
pumpum Avatar asked Jul 10 '18 02:07

pumpum


Video Answer


2 Answers

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!

like image 132
tskjetne Avatar answered Sep 25 '22 08:09

tskjetne


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

like image 33
joknawe Avatar answered Sep 26 '22 08:09

joknawe