![](/img/trans.png)
[英]React Native: Can't perform a React state update on an unmounted component
[英]Why am I getting the following React Native warning: Can't perform a React state update on an unmounted component
我正在尝试构建一个 React Native 应用程序,但我对 React/RN 生态系统仍然有点陌生,所以我可能只是误解了我遇到的问题的一些明显问题。
我有一个应用程序,其中许多页面的结构如下:
<View>
<NavComponent />
<View>
{/* Page component structure/logic here */}
</View>
</View>
NavComponent
负载与可切换导航菜单TouchableOpacity
元素像下面这样:
Go to Screen #1
Go to Screen #2
Go to Screen #3
我遇到的问题(也许这不是 React/RN 工作原理的问题)是,如果我从屏幕 #1 开始,打开导航,转到屏幕 #2,再次打开导航,然后回到屏幕 #1,即使屏幕 #1 再次出现,屏幕 #1 的实际渲染函数似乎不会再次被调用,并且由于NavComponent
是每个屏幕渲染的一部分,当我尝试要再次从屏幕 #1 打开导航,我收到以下警告:
警告:无法对卸载的组件执行 React 状态更新。 这是一个空操作,但它表明您的应用程序中存在内存泄漏。 要修复,取消 %s 中的所有订阅和异步任务。%s,useEffect 清理函数...
同样,也许我使用该应用程序的方法一开始就有缺陷,但基本上,当我从一个屏幕从导航转到另一个屏幕时,我总是希望新屏幕从头开始重新渲染(包括最初的 Ajax 调用数据) .
下面是一个更加充实的屏幕渲染函数示例(它们都遵循相同的基本模式):
const screen1 = ({ navigation }) => {
const [serverData, setServerData] = useState(null);
useEffect(() => {
// getPageData is a custom method I added to axios.
axios.getPageData('/api/url/here', (data) => {
setServerData(data);
});
}, []);
if (serverData) {
const { meta, user, data } = serverData;
return (
<View>
<NavComponent />
<View style={styles.container}>
{/* Page component structure/logic here */}
</View>
</View>
);
}
return null;
};
例如,如果我在上面的渲染函数的开头添加了一个console.log
,它会在第一次加载屏幕时调用,但是如果我转到屏幕 #2 然后通过导航组件返回屏幕 #1 , console.log
不再输出。 为什么?
对于它的价值,我在NavComponent
使用标准的navigation.navigate('ScreenName')
从一个屏幕到NavComponent
屏幕。
关于如何修复警告(和/或更好地设计应用程序)以便我可以在每个页面上都有该导航的任何建议将不胜感激。 谢谢你。
您的 api 调用导致警告,在 react/native 生态系统中,当从树中删除组件时,开发人员需要取消所有订阅(事件侦听器)和异步任务(从网络获取数据),这些功能需要由开发人员取消,因为 react/native 无法为您执行此操作。
要在基于类的组件中处理它,您需要执行componentWillUnmount
并删除那里的订阅
class MyClass extends Component {
componentWillUnmount() {
// remove listeners and cancel requests
}
但是在现代钩子组件中,您需要返回一个清理函数,一个在 useEffect 中返回的函数,它将被 react 调用以取消您所做的任何订阅,在您的情况下,只需返回一个清理函数即可为您删除该警告
const [mounted, setIsMounted] useState(false)
useEffect(() => {
// getPageData is a custom method I added to axios.
setIsMounted(true)
axios.getPageData('/api/url/here', (data) => {
if(isMounted)
setServerData(data);
});
return () => {
setIsMounted(false)
}
}, []);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.