gpt4 book ai didi

reactjs - 如何取消对 componentWillUnmount 的获取

转载 作者:行者123 更新时间:2023-12-03 12:54:22 24 4
gpt4 key购买 nike

我认为标题已经说明了一切。每次卸载仍在获取的组件时,都会显示黄色警告。

安慰

Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but ... To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.

  constructor(props){
super(props);
this.state = {
isLoading: true,
dataSource: [{
name: 'loading...',
id: 'loading',
}]
}
}

componentDidMount(){
return fetch('LINK HERE')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson,
}, function(){
});
})
.catch((error) =>{
console.error(error);
});
}

最佳答案

当您触发 Promise 时,可能需要几秒钟的时间才能解决,到那时用户可能已导航到应用程序中的另一个位置。因此,当 Promise 解析 setState 在未安装的组件上执行时,您会收到错误 - 就像您的情况一样。这也可能导致内存泄漏。

这就是为什么最好将一些异步逻辑移出组件的原因。

否则,您将需要以某种方式 cancel your Promise 。或者 - 作为最后的手段(这是一种反模式) - 您可以保留一个变量来检查组件是否仍然已安装:

componentDidMount(){
this.mounted = true;

this.props.fetchData().then((response) => {
if(this.mounted) {
this.setState({ data: response })
}
})
}

componentWillUnmount(){
this.mounted = false;
}

我会再次强调这一点 - 这个 is an antipattern但对于您的情况来说可能就足够了(就像他们对 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://codesandbox.io/s/86n1wq2z8

关于reactjs - 如何取消对 componentWillUnmount 的获取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49906437/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com