Understanding Events in React

Understanding Events in React

Subscribe to my newsletter and never miss my upcoming articles

Disclaimer: React official docsite ⚛️ is itself a good resource to understand events and their handling in the React ecosystem.

Then, why do I have to write about it again?

Well, in this blog post, I have explained what events in React are composed of and have added some nuances and explained them based on my experience working with React for over 3 years now. So, in short, this is my personal take on understanding events in React. Everything under one hood

In my next blog, I will be writing about how events are handled in React, alongwith citing some caveats and performance enhancements that you can do while handling events.

If you came to React from the vanilla JS world (like I did), you will have to understand that events in React are not the usual browser’s native event that we are familiar with. These are synthetic events.

image.png As the meaning of the word "synthetic" suggests, it is indeed a wrapper on the top of the browser’s native events to make them cross-browser compatible. It has the same interface as the browser’s native event, including stopPropagation() and preventDefault(), etc. except these events work identically across all browsers. The synthetic events are different from, and do not map directly to, the browser’s native events. However if you want to use the underlying browser event, you can use the nativeEvent attribute to get it.

For example in onMouseLeave event.nativeEvent will point to a mouseout event.


What are the other major differences between the synthetic and the browser's native events?

Well, there is none actually. Yes, there are syntactical and logical differences in the way they are handled in React and the attributes they have. But, if you talk about any major structural difference apart from the points I mentioned above, there is none actually.

If you are using React v<17.0.0, then there is one point which is of your interest and is actually used to be a big difference between synthetic and native events

Synthetic events used to be pooled before React 17

Event Pooling

Don't get overwhelmed with the name here. It is actually a pretty easy to understand concept, which is now no more valid in React after the v17 came out. Actually, it was introduced in React as an optimization feature, which would improve the performance of handling events in React.

Wait wait wait...what the heck is Event Pooling ?

Events in React are pooled, this means that the SyntheticEvent object will be reused and all properties will be nullified after the event handler has been called. In simpler terms, as soon as the eventHandler is done with its job, the same event object will be recycled and made new for handling other events. React used to reuse the event objects between different events for performance in old browsers, and set all event fields to null in between them.

For example till React v16

function handleChange(e) {
  // This won't work because the event object gets reused.
  setTimeout(() => {
    console.log(e.target.value); // Too late!
  }, 100);

As soon as the setTimeout function is encountered, the work goes to the browser's timer API (read about execution life cycle in JS) and the job of the handleChange function is done here. So, the same e then and there, is nullified and made new. So, when after 100ms, you would want to get the value of e.target.value, React used to throw error.

If you need to access event object’s properties after the event handler has run, you need to call e.persist():

function handleChange(e) {
  // Prevents React from resetting its properties:
  setTimeout(() => {
    console.log(e.target.value); // not too late!
  }, 100);

React 17 removes the “event pooling” optimization from React, the reason being that in modern browsers, it doesn’t improve performance.**

function handleChange(e) {
  // setState is a asynchronous function
  setData(data => ({
    /* This crashes in React 16 and earlier
         but works fine from v17 onwards */
    text: e.target.value

To understand more about how setState works under the hood, check this out.

Note that e.persist() is still available on the React event object, but now it doesn’t do anything.


To summarize, what we learnt till now:

  1. Synthetic events are a wrapper over the browser's native event.

  2. They are cross-browser compatible, meaning they are supported in all the browsers are not browser specific

  3. There is a way to use native events too, with the help of nativeEvent attribute on the synthetic event.

  4. Before React 17, the React synthetic events used to be pooled.

  5. To use the same event even after the event handler has run, you could use the persist method on SyntheticEvent.

Well, now you have a fair idea of what are events like in the React world.

In my next blog, I will be writing about how events are handled in React, alongwith citing some caveats and performance enhancements that you can do while handling events.

Stay tuned 📻

If you liked what you read 🧑‍🏫 and got to learn new things, do hit like 👍 and subscribe 🔖to my newsletter to get instantly notified whenever I drop in new content. And don't forget to follow 🚀 me on

Hashnode - Rajat Jain

Twitter - @rajat_codes

Instagram - @javascript_to_the_rescue

LinkedIn - Rajat Jain

Interested in reading more such articles from Rajat Jain?

Support the author by donating an amount of your choice.

Recent sponsors
Share this
Proudly part of