Reputation: 263
I'm new to React and I'm getting this error:
Warning: 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. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
From what I understand, it appears as though I have a memory leak and need a useEffect cleanup for my useCallback hook?
I have tried adding a useRef
to check mount but the return doesn't change the state to false.
const MyComponent = ({data}) => {
const mounted = useRef(true);
const [loading, setLoading] = useState(false);
const isLoading = useCallback(async () => {
setLoading(true);
if (data) {
console.log('YAY DATA: ', data);
}
return () => {
setLoading(false); // unreachable code
mounted.current = false; // does this do the cleanup?
};
}, [loading]);
return (
//...some component
);
};
export default MyComponent;
Upvotes: 12
Views: 15244
Reputation: 6607
If you perform an async operation that, on completion, needs to set something to the state, you must make sure that the component is still mounted before updating the state.
In order to do so, you try something like this:
const MyComponent = (props) => {
const mounted = useRef(false);
useEffect(() => {
mounted.current = true; // Will set it to true on mount ...
return () => { mounted.current = false; }; // ... and to false on unmount
}, []);
const [loading, setLoading] = useState(false);
const [data, setData] = useState([]);
const myAsyncCallback = useCallback(async () => {
setLoading(true);
// Await for an async function...
const data = await yourAsyncFunction(...); // Complete with proper code here
// While waiting for yourAsyncFunction to be done,
// It's possible that your component had been unmounted.
// Therefore, you have to check if the component is still mounted before updating states
if (mounted.current) {
setLoading(false);
setData(data);
}
}, []);
return (
//...some component that calls myAsyncCallback
);
};
export default MyComponent;
Upvotes: 26
Reputation: 102
As useEffect cleanUp on component unmount, you can not update the state (and since it unmounts where value could be stored)
Your code seem to be a code where api call is done in the useEffect .like that :
useEffect(() => {
let mounted = true
fetchAPI.then(() => {
if (mounted) {
setloading(false)
}
})
return function cleanup() {
mounted = false
}
}, [])
If it's that look at here : https://dev.to/otamnitram/react-useeffect-cleanup-how-and-when-to-use-it-2hbm
Upvotes: 1