Reputation: 420
I get this 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.'
Code
const [photo, setPhoto] = useState([]);
useEffect(() => {
fetch('/mypost', {
headers: {
cookie: 'access_token',
},
})
.then((res) => res.json())
.then((data) => {
setPhoto(data.mypost);
});
}, []);
The data is fetched but I could'nt figure what to add in the clean up. Any suggestions?
Upvotes: 0
Views: 1587
Reputation: 3450
try the following code:
useEffect(() => {
let isMounted = true;
fetch('/mypost', {
headers: {
cookie: 'access_token',
},
})
.then((res) => res.json())
.then((data) => {
if (isMounted) setPhoto(data.mypost);
});
//cleanup function
return () => { isMounted = false };
}, []);
Upvotes: 1
Reputation: 1597
import React, {useState} from "react";
import { useAsyncEffect } from "use-async-effect2";
import cpFetch from "cp-fetch";
export default function TestComponent(props) {
const [photo, setPhoto] = useState([]);
useAsyncEffect(
function* () {
const response = yield cpFetch('/mypost');
setPhoto((yield response.json()).mypost);
},
[]
);
return <div></div>;
}
Upvotes: 1
Reputation: 202751
The problem is that the fetch request resolves but the component has unmounted (for some reason) and so the state update can't occur now.
You need to use an Abort Controller to cancel in-flight requests. If the component unmounts, an effect cleanup function cancels the fetch request.
useEffect(() => {
const controller = new AbortController(); // <-- create controller
const { signal } = controller; // <-- get signal for request
fetch('/mypost', {
headers: {
cookie: 'access_token',
},
signal, // <-- pass signal with options
})
.then((res) => res.json())
.then((data) => {
setPhoto(data.mypost);
});
return () => controller.abort(); // <-- return cleanup function to abort
}, []);
Note: When
abort()
is called, thefetch()
promise rejects with anAbortError
.
You will likely need to catch this promise rejection somewhere. You can append a .catch
block to the Promise chain.
fetch('/mypost', {
headers: {
cookie: 'access_token',
},
signal, // <-- pass signal with options
})
.then((res) => res.json())
.then((data) => {
setPhoto(data.mypost);
})
// catch any rejected fetch promises (including aborted fetches!)
.catch(console.error);
Upvotes: 3