当您触发Promise时,它可能需要花费几秒钟的时间才能解决,到那时,用户可能已经导航到应用程序中的另一个位置。因此,
setState在未安装的组件上执行Promise
resolves时,您会得到一个错误-就像您的情况一样。这也可能导致内存泄漏。
这就是为什么最好将某些异步逻辑移出组件。
否则,您将需要以某种方式取消Promise。另外,作为一种不得已的技术(这是一种反模式),您可以保留一个变量来检查组件是否仍处于安装状态:
componentDidMount(){ this.mounted = true; this.props.fetchData().then((response) => { if(this.mounted) { this.setState({ data: response }) } })}componentWillUnmount(){ this.mounted = false;}我会再次强调-这是一种反模式,但在您的情况下可能就足够了(就像他们对
Formik实现所做的一样)。
GitHub上的类似讨论
编辑:
这可能是我如何使用Hooks解决相同的问题(除了React之外什么也没有):
选项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; // track whether component is mounted request.get(url) .then(result => { if (isMounted) { setState(result); } }); return () => { // clean up isMounted = false; }; }, []); // only on "didMount" return value;}选项B: 或者,
useRef其行为类似于类的静态属性,这意味着它的值更改时不会使组件重新呈现:
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;}// or extract it to custom hook:function useIsMounted() { const isMounted = React.useRef(true) useEffect(() => { return () => { isMounted.current = false; }; }, []); return isMounted; // returning "isMounted.current" wouldn't work because we would return unmutable primitive}示例:https://presandbox.io/s/86n1wq2z8



