Reputation: 1766
Greetings I'm trying to debug some code right now, not sure how to fix this useEffect that I have in my header to detect for screen size view. Here is the error I'm getting for the useEffect:
Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application.
My code:
const [state, setState] = useState({
mobileView: false,
drawerOpen: false,
});
const { mobileView, drawerOpen } = state;
useEffect(() =>
{
const setResponsiveness = () =>
{
return window.innerWidth < 1000
? setState((prevState) => ({ ...prevState, mobileView: true }))
: setState((prevState) => ({ ...prevState, mobileView: false }));
};
setResponsiveness();
window.addEventListener("resize", () => setResponsiveness());
}, []);
The dependency array is already empty, im not sure what else to put in there though?
Upvotes: 2
Views: 1281
Reputation: 1763
It's not useEffect that is causing the problem, it's window resize event which is being excuted whenever window size changes.
You are adding resize
event to window when your function mounts. but when you unmount the component, resize
event is still listening and whenever window size changes your setResponsiveness
function will be called. and setResponsiveness
will try to update the state values of unmounted component. So basically your functional component is leaking memory because even though it has unmounted setResponsiveness
is still attached to as a callback to windo resize
event.
You should always remove component specific event listener either in componentWillUnmount
or in useEffect
return function, depending on component type.
const [state, setState] = useState({
mobileView: false,
drawerOpen: false,
});
const { mobileView, drawerOpen } = state;
function setResponsiveness() {
return window.innerWidth < 1000
? setState((prevState) => ({ ...prevState, mobileView: true }))
: setState((prevState) => ({ ...prevState, mobileView: false }));
}
useEffect(() => {
setResponsiveness();
window.addEventListener("resize", setResponsiveness);
// return a cleanup function which will remove the event listener
return () => {
window.removeEventListener("resize", setResponsiveness);
};
}, []);
Upvotes: 3
Reputation: 370669
Remove the listener by returning a callback from useEffect
, which'll run when the component unmounts.
useEffect(() => {
const setResponsiveness = () => {
return window.innerWidth < 1000
? setState((prevState) => ({ ...prevState, mobileView: true }))
: setState((prevState) => ({ ...prevState, mobileView: false }));
};
setResponsiveness();
window.addEventListener("resize", setResponsiveness);
return () => window.removeEventListener("resize", setResponsiveness);
}, []);
Upvotes: 1