React SyntheticEvent reuse

Ceci García García
Trabe
Published in
2 min readOct 29, 2018
Photo by Jared Rice on Unsplash

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 preventDefault() and stopPropagation().

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.

Solution 1: event.persist()

Calling 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:

The 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.

Summing up

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.

--

--