Khi bạn kích hoạt Lời hứa, có thể mất vài giây trước khi nó giải quyết và vào thời điểm đó, người dùng có thể đã điều hướng đến một vị trí khác trong ứng dụng của bạn. Vì vậy, khi giải quyết Promise setState
được thực thi trên thành phần chưa được gắn kết và bạn gặp lỗi - giống như trong trường hợp của bạn. Điều này cũng có thể gây rò rỉ bộ nhớ.
Đó là lý do tại sao tốt nhất là di chuyển một số logic không đồng bộ của bạn ra khỏi các thành phần.
Nếu không, bằng cách nào đó, bạn sẽ cần phải hủy bỏ Lời hứa của mình . Ngoài ra - như một kỹ thuật cuối cùng (đó là một phản vật chất) - bạn có thể giữ một biến để kiểm tra xem thành phần có còn được gắn kết hay không:
componentDidMount(){
this.mounted = true;
this.props.fetchData().then((response) => {
if(this.mounted) {
this.setState({ data: response })
}
})
}
componentWillUnmount(){
this.mounted = false;
}
Tôi sẽ nhấn mạnh điều đó một lần nữa - đây là một phản vật chất nhưng có thể đủ trong trường hợp của bạn (giống như họ đã làm với Formik
việc triển khai).
Một cuộc thảo luận tương tự trên GitHub
BIÊN TẬP:
Đây có lẽ là cách tôi giải quyết vấn đề tương tự (không có gì ngoài React) với Hooks :
LỰA CHỌN 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;
}
LỰA CHỌN B: Ngoài ra useRef
, nó hoạt động như một thuộc tính tĩnh của một lớp, nghĩa là nó không thực hiện kết xuất thành phần khi giá trị của nó thay đổi:
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;
}
Ví dụ: https://codesandbox.io/s/86n1wq2z8