React: [bug] React onChange Synthetic / Proxy events are being recycled, issue when handler is debounced

Created on 20 Sep 2016  ·  3Comments  ·  Source: facebook/react

What is the current behavior?

Confirmed as of 0.14.7 but also happens today in 15.3.2.

https://jsfiddle.net/dimitar/7ktbfetb/

class Foo extends React.Component {
    render(){
    const handleChange = _.debounce(this.props.onChange, 500);
    return <input onChange={handleChange} />
  }
}

ReactDOM.render(<Foo onChange={e => console.log(e.target, e)} />, document.querySelector('div'));

expect to get e.target, get null

without the debounce, works as expected. https://jsfiddle.net/dimitar/7ktbfetb/1/

possibly related to https://github.com/facebook/react/commit/3285d834402a60d241188a1deacf8250b50239cf - for https://github.com/facebook/react/blob/master/CHANGELOG.md#react-9

Most helpful comment

For anybody looking for a workaround, you can use e.persist()

eg. return <input onChange={e => handleChange(e.persist()||e)} />

All 3 comments

For anybody looking for a workaround, you can use e.persist()

eg. return <input onChange={e => handleChange(e.persist()||e)} />

This is because of how debounce works. It's going to use setTimeout to push out a call to the next event loop. As you noted, because of pooling this means that React has already returned the synthetic event back to the pool and reset the fields. If you are using debounce or anything else that requires the event to exist outside of React's event handler (eg async code), then you need to persist.

This is by design so there's nothing to do about this right now. There's some discussion in #6190 about potentially removing the pooling, which should make your code work without explicit persisting.

this goes contrary to the very principles react set out to solve around flow of data, immutability and avoiding side effects. you are passing an object to a component but it's only a snapshot that has to be used within the same event loop because you distrust the GC and users whom may inadvertently create a leak...

whereas it may have been a good idea at the time, some of us only need to support evergreen browsers that are capable of adequate GC. perhaps, in the interim while this approach is being reconsidered, a flag/env var can be set to switch off pooling.

Was this page helpful?
0 / 5 - 0 ratings