When working with DOM events, we have to take care of React's event pooling. Let's explain better what it is: React use a cross-browser wrapper around the browser’s native events called SyntheticEvent. With this wrapper events work identically across all browsers.
With the SyntheticEvent wrapper, DOM events are pooled. This means that the Event object will be reused, and all properties will be nullified after the event callback has been invoked (React does this for performance reasons) What you need to know as a React developer is: in order to use DOM events in an asynchronous way you need to persist the event. By asynchronous I mean using the event inside promises, throttle/debounce, timeouts and setState operations
onClick = e => {
alert(`SYNC -> hasNativeEvent=${!!e.nativeEvent}`)
setTimeout(() => {
alert(`ASYNC -> hasNativeEvent=${!!e.nativeEvent}`);
}, 0)
}
The 2nd (async) will print hasNativeEvent=false
because the event properties have been cleaned up.
onClick = e => {
e.persist()
alert(`SYNC -> hasNativeEvent=${!!e.nativeEvent}`)
setTimeout(() => {
alert(`ASYNC -> hasNativeEvent=${!!e.nativeEvent}`);
}, 0)
}
The 2nd (async) will print hasNativeEvent=true
because persist allows you to avoid putting the event back in the pool.