Sometimes, we want to detect clicks outside a React component.
In this article, we’ll look at how to detect clicks outside a React component.
Detect Clicks Outside a React Component
To detect clicks outside a React component, we can create our own hook that detects whether we clicked outside the component with the DOM node’s contains
method.
For instance, we can write:
import React, { useRef, useEffect } from "react";
const useOutsideAlerter = (ref) => {
useEffect(() => {
const handleClickOutside = (event) => {
if (!ref.current?.contains(event.target)) {
console.log("clicked outside");
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [ref]);
};
export default function App() {
const wrapperRef = useRef(null);
useOutsideAlerter(wrapperRef);
return <div ref={wrapperRef}>hello world</div>;
}
We create the useOutsideAlerter
hook that takes a ref parameter.
Then we call the useEffect
hook with an array with the ref
as the 2nd argument to watch it for changes.
In the useEffect
callback, we define the handleClickOutside
function that checks if we clicked outside the component assigned to the ref
with:
!ref.current?.contains(event.target)
event.target
is the element we clicked on.
Therefore, if that is false
, we clicked outside the component assigned to the ref
and we log 'clicked outside'
.
Next, we call document.addEventListener
with 'mousedown'
to listen to the mousedown event.
And we use handleClickOutside
as the mousedown event listener.
Then we return a function that calls document.removeListener
with 'mousedown'
and handleClickOutside
to remove the event listener when the component unmounts.
In App
, we assign a ref to the div and we called the useOutsideAlerter
hook with the ref
.
So when we click outside the div, we see 'clicked outside'
logged.
Conclusion
To detect clicks outside a React component, we can create our own hook that detects whether we clicked outside the component with the DOM node’s contains
method.