The under hood of React event —— Synthetic Event
When we attach an event on one JSX element, it's really simple and straight forward: just use camelCase in the tag, like <a href="https://google.com" onClick={clickHandler}>Foo</a>
.
However, when you inspect the event trigger in clickHandler
, you will find something interesting.
const clickHandler = (event) => {
event.preventDefault();
console.log('target', event.target);
console.log('current target', event.currentTarget);
};
After clicking, in the browser dev tool console, we can get the correct output:
target <a href="https://google.com">Foo</a>
current target <a href="https://google.com">Foo</a>
event.target
tells where the event started.
event.currentTarget
tells us on which element the event was attached or the element whoseeventListener
triggered the event.
Then if we print out the event
object:
Hmmm, I won't show all properties and functions here. They are too many :P
And we also find the __proto__
of this event is a class:
__proto__: Class
constructor: f Class()
__proto__: SyntheticEvent
What's this Synthetic Event ?
According to the official document of React, SyntheticEvent is "a cross-browser wrapper around the browser’s native event" and "has the same interface as the browser’s native event".
That means React encapsulates the browser native event object within this synthetic event and implements all native interfaces, including properties and functions.
Let's do this in clickHandler
:
const clickHandler = (event) => {
event.preventDefault();
console.log('native target', event.nativEvent.target);
console.log('native current target', event.nativEvent.currentTarget);
};
In the console, we have:
native target <a href="https://google.com">Foo</a>
native current target #document
Which means, React attaches the native event listener on global document
object.
let's have a summary for React event system:
- React event is SyntheticEvent, and simulate all abilities of DOM event;
- If you need native event, just use
event.nativeEvent
; - All DOM events are attached on
document
object.
But why? A couple of reasons:
- Better cross-platform performance. E.g. React team just needs to change the implementation layer when moving React from web to mobile, rather than rewrite the whole system;
- Attach on document, to reduce memory cost as this will prevent too often untie when components are unmounted;
- It's convenient for unified management of events, with this unified entry point.