React implements its own event system in order to provide cross-browser compatibility support. Basically, React wraps the browser native event into an instance of the React
SyntheticEvent and passes it in React event handlers.
SyntheticEvent has the same interface as a native event which means that you can use methods like
How does React manage the event system?
For performance reasons, React reuses the
SyntheticEvent objects by pooling them. This means that the
SyntheticEvent object is reused, so after an event handler is invoked all the properties on
event.target are nullified.
“Warning: This synthetic event is reused for performance reasons”
This warning is triggered when we try to access to a React synthetic event in an asynchronous way. Because of the reuse, after the event callback has been invoked the synthetic event object will no longer exist so we cannot access its properties.
The most common example of an asynchronous access to a
SyntheticEvent is within a
setState. When we update a component state through the updater function, the updater will be called asynchronously and the event will be already nullified.
event.persist() on the synthetic event removes the event from the pool allowing references to the event to be retained asynchronously.
Solution 2: cache the needed properties
We can store the event properties in the event handler and pass them to the asynchronous callback instead of accessing the event directly from the asynchronous callback:
Debouncing a synthetic event handler.
Another common example apart from
setState is a debounced callback:
debounce method from lodash creates the function which will be invoked asynchronously so if we try to access the object directly from the debounced callback, the synthetic event will be already nullified.
The example below fixes the problem by caching the event properties. In this case, we access the event value out of the debounced code and pass it to the debounced callback.
React wraps native browser events into instances of the
SyntheticEvent. A synthetic event cannot be accessed asynchronously because React reuses it once its handler is called. As possible solutions, we can call
event.persist() or we can cache the needed event properties until they’re finally used.