Kiedy uruchomisz obietnicę, może minąć kilka sekund, zanim zostanie rozwiązana, a do tego czasu użytkownik mógł przejść do innego miejsca w Twojej aplikacji. Więc kiedy Promise rozwiązuje problem, setStatejest wykonywany na niezmontowanym komponencie i pojawia się błąd - tak jak w twoim przypadku. Może to również powodować wycieki pamięci.
Dlatego najlepiej jest przenieść część logiki asynchronicznej z komponentów.
W przeciwnym razie będziesz musiał w jakiś sposób anulować swoją obietnicę . Alternatywnie - w ostateczności (jest to antywzór) - możesz zachować zmienną, aby sprawdzić, czy komponent jest nadal zamontowany:
componentDidMount(){
this.mounted = true;
this.props.fetchData().then((response) => {
if(this.mounted) {
this.setState({ data: response })
}
})
}
componentWillUnmount(){
this.mounted = false;
}
Podkreślę to jeszcze raz - jest to przeciwieństwo, ale w twoim przypadku może wystarczyć (podobnie jak w przypadku Formikimplementacji).
Podobna dyskusja na GitHubie
EDYTOWAĆ:
Prawdopodobnie w ten sposób rozwiązałbym ten sam problem (nie mając nic poza Reagowaniem) z hookami :
OPCJA A:
import React, { useState, useEffect } from "react";
export default function Page() {
const value = usePromise("https://something.com/api/");
return (
<p>{value ? value : "fetching data..."}</p>
);
}
function usePromise(url) {
const [value, setState] = useState(null);
useEffect(() => {
let isMounted = true;
request.get(url)
.then(result => {
if (isMounted) {
setState(result);
}
});
return () => {
isMounted = false;
};
}, []);
return value;
}
OPCJA B: Alternatywnie, z useRefktórym zachowuje się jak statyczna właściwość klasy, co oznacza, że nie zwraca komponentu, gdy zmienia się jego wartość:
function usePromise2(url) {
const isMounted = React.useRef(true)
const [value, setState] = useState(null);
useEffect(() => {
return () => {
isMounted.current = false;
};
}, []);
useEffect(() => {
request.get(url)
.then(result => {
if (isMounted.current) {
setState(result);
}
});
}, []);
return value;
}
function useIsMounted() {
const isMounted = React.useRef(true)
useEffect(() => {
return () => {
isMounted.current = false;
};
}, []);
return isMounted;
}
Przykład: https://codesandbox.io/s/86n1wq2z8