问题
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?
回答1:
Issue
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.
Solution
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);
回答2:
Generic JSON fetch demo
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>;
}
回答3:
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
rreturn () => { isMounted = false };
}, []);
来源:https://stackoverflow.com/questions/65528967/useeffect-cleanup-function-in-react