React SyntheticEvent reuse

Photo by on

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 and passes it in React event handlers. SyntheticEvent has the same interface as 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 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 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.

Trabe

We are a development studio. We use Java, Rails, and JavaScript. This is where we write about the technologies we use at Trabe.

Thanks to David Barral and Roman Coedo.

Ceci García García

Written by

Software developer @trabe.

Trabe

Trabe

We are a development studio. We use Java, Rails, and JavaScript. This is where we write about the technologies we use at Trabe.