3

In the following, the handleChange method throws an error when, inside setState, I use a function to return an object, but works fine when I update inputvalue directly as an object

   class App extends React.Component {
  constructor (props) {
      super(props);
      this.state = {
          inputvalue: ''
      }
      this.handleChange = this.handleChange.bind(this);
  }

  handleChange (event) {
    event.preventDefault();
    this.setState(() => {
      return {inputvalue: event.target.elements.name.value}//throws an error but works fine if I use just use object with out using a functon to return
    }       
    );
  }

  render() {
    return (
      <div>
          <form onSubmit={this.handleChange}>
              <label>Name  </label>
              <input type="text" name="option"  />
              <button>submit</button>
          </form>
         <p> {this.state.inputvalue}</p>
      </div>
    );
  }
}

render(<App />, document.getElementById('app'));

Warning that happens:

Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the method stopPropagation on a released/nullified synthetic event. This is a no-op function. If you must keep the original synthetic event around, use event.persist(). See https://reactjs.org/docs/events.html for more information.

evolon
  • 1,276
  • 1
  • 10
  • 18
Karth
  • 55
  • 6
  • 2
    what's the error? – Y_Moshe Jan 21 '20 at 17:07
  • 1
    I don't see any error text in your post, please edit it in. And on a more practical note, why would you return anything at all? `setState` completely ignores function returns from a post-state-update callback. If you need access to the value you're returning, that is _literally_ what component state is already for: don't return it after updating the state, _update the state with that value_ to begin with =) – Mike 'Pomax' Kamermans Jan 21 '20 at 17:14

2 Answers2

2

Based on this:

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.

If you want to access the event properties in an asynchronous way, you should call event.persist() on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code.

You should call persist method when using a function as updater.

handleChange (event) {
    event.persist();

    this.setState(() => {
        ...
    }
}

Take a look at this answer:

TypeError: evt.target is null in functional setState

evolon
  • 1,276
  • 1
  • 10
  • 18
  • super helpful, the persist method made the error go away. I also had to use preventDefault from my code editor refreshing immediately. thanks. – Karth Jan 21 '20 at 21:44
-2

i think u are accessing here wrong:

event.target.elements.name.value

should be

event.target.elements.option.value // because u set the name attribute to option (name="option") on the input element

and if i don't mistake the error is that u trying to access null reference right?

Y_Moshe
  • 424
  • 1
  • 5
  • 11
  • Thanks, that was a typo, should be option. Doesn't solve the original problem but definitely doesn't help that i made that typo :) – Karth Jan 21 '20 at 21:43