React has its own event system that's similar to the DOM event system, but that works in parallel to it. That means that React event handlers are assigned differently than DOM event listeners.
React Event Handlers
You can handle events in React by passing an event handler function as a prop JSX element:
import { MouseEvent } from "react";
function MyComponent() {
const handleButtonClick = (e: MouseEvent<HTMLButtonElement>) => {
// Called when the button is clicked
}
return (
<button onClick={handleButtonClick}>
Click me!
</button>
)
}The event handler props are all camel-cased and accept a callback function. Some commonly used ones are onClick, onChange and onSubmit. The callback function will receive SyntheticEvent as the parameter.
DOM Event Handlers in React
It's sometimes necessary to use the DOM event system, for instance when integrating with 3rd party libraries or listening to window events.
You should use the useEffect hook to add event listeners in React. Here's how to listen to events on window in React:
function MyComponent() {
useEffect(() => {
const handleWindowResize = (e: UIEvent) => {
// Called when browser window is resized
};
window.addEventListener("resize", handleWindowResize);
return () => {
window.removeEventListener("resize", handleWindowResize);
};
}, []);
return <>...</>;
}window.- Add a call to
useEffectand provide[]as the dependency list to only register the event listener once when the component is mounted. - Create a handler function inside of the
useEffecthook's callback function. - Bind the event handler to an event using
addEventListeneron the DOM element. - Return a cleanup function for the
useEffecthook that removes the assigned event handler.
Assigning DOM events to React elements
To assign the event listener to the React element you need to first get the reference to the underlying DOM element. This is commonly done using the useRef hook:
function MyComponent() {
const buttonRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
// 👇 Get the DOM element from the React element
const element = buttonRef.current;
if (!element) return;
const handleButtonClick = (e: MouseEvent) => {
// Called when button is clicked
};
element.addEventListener("click", handleButtonClick);
return () => {
element.removeEventListener("click", handleButtonClick);
};
}, []);
return <button ref={buttonRef}>Click me!</button>;
}useRef to get their references.- Call the
useRefand assign its value to therefprop on the React element. - In the
useEffecthook, get the reference to the DOM element fromcurrentproperty on the ref object. Check that it's not null. - Add the DOM event listener like before using
addEventListener.
Conclusion
Always prefer to use the React event system, because it fixes certain inconsistencies, and working with it is generally easier.
In the rare cases when you do need DOM event listeners, assign them in the useEffect hook. You should first have the reference to the DOM element which you can get using the useRef hook or simply by querying it directly, e.g. window, document.body or document.querySelector(...).