无法对未挂载的组件执行 React 状态更新 - 内存泄漏?



我曾尝试在useEffectreturn () => mounted.current = false的开头使用mounted = useRef()let mounted.current = true,但仍然收到以下错误消息:

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
in NameDetails (at TitleRow.js:114)
in RCTView (at View.js:34)
in View (at TitleRow.js:113)
in titleRow (at TodayTitleList.js:154)
in RCTView (at View.js:34)
in View (at VirtualizedList.js:2015)
in VirtualizedListCellContextProvider (at VirtualizedList.js:2030)
in CellRenderer (at VirtualizedList.js:807)
in RCTScrollContentView (at ScrollView.js:1107)
in RCTScrollView (at ScrollView.js:1213)
in ScrollView (at ScrollView.js:1264)
in ScrollView (at VirtualizedList.js:1250)
in VirtualizedListContextProvider (at VirtualizedList.js:1080)
in VirtualizedList (at FlatList.js:620)
in FlatList (at TodayTitleList.js:149)
in RCTSafeAreaView (at SafeAreaView.js:51)
in SafeAreaView (at TodayTitleList.js:136)

查看堆栈跟踪,我猜测错误在NameDetails文件中,并且它涉及其中的useEffect。是这样吗?

以下是我的代码:

const NameDetails = ({ title }) => {
const [color, setColor] = useState('#000');
useEffect(() => {
//let mounted = true; 
const getColor = async (id) => {
const chosenColor = await getColorFortitle(id);
setColor(chosenColor);
//return () => { mounted = false };
};
getColor(title.id);
});
return (
<View>
...
</View>
);
};
export default NameDetails;

更多信息:当我注销并尝试再次登录时,会发生此错误,而且这种情况只在某些时候发生。

const NameDetails = ({ title }) => {
const [color, setColor] = useState('#000');
useEffect(() => {
let mounted = true; 

const getColor = async (id) => {
const chosenColor = await getColorFortitle(id);
mounted && setColor(chosenColor);
};
getColor(title.id);
return () => { mounted = false };
}, [title.id]);
return (
<View>
...
</View>
);
};

一种更可取的方法:

const NameDetails = ({ title }) => {
const isMounted = React.useRef(true);
React.useEffect(() => () => (isMounted.current = false), []);

const [color, setColor] = useState('#000');
useEffect(() => {
const getColor = async (id) => {
const chosenColor = await getColorFortitle(id);
isMounted.current && setColor(chosenColor);
};
getColor(title.id);
}, [title.id]);
return (
<View>
...
</View>
);
};

或者,如果你不确定那里发生了什么,你可以尝试使用我的库和基于生成器的异步挂钩,在那里你不必担心卸载:

import React, { useState } from "react";
import { useAsyncEffect } from "use-async-effect2";
const NameDetails = ({ title }) => {     
const [color, setColor] = useState('#000');
useAsyncEffect(function*(){
const chosenColor = yield getColorFortitle(title.id);
setColor(chosenColor);
}, [title.id]);
return (
<View>
...
</View>
);
};

请检查我的代码我希望这对你有帮助。

const NameDetails = ({ title }) => {
const [color, setColor] = useState('#000');
const [mounted, setMount] = useState(true);
useEffect(() => { 
const getColor = async (id) => {
const chosenColor = await getColorFortitle(id);
setColor(chosenColor);
return () => { setMount = false };
};
getColor(title.id);
});
return (
<View>
...
</View>
);
};
export default NameDetails;

我只使用一种状态。因此,您可以使用状态更改值。根据您的代码运行。

每次组件重新渲染时都使用useEffect:向useEffect添加一个空依赖项以仅在第一个呈现上运行

const mounted = useRef(false);
useEffect(() => mounted.current = true, []);

useEffect(() => {
const getColor = async (id) => {
const chosenColor = await getColorFortitle(id);
setColor(chosenColor);
}
if(mounted.current)
getColor(title.id);
return () => { mounted.current = false };
}, []);

最新更新