setState导致主题订阅内部内存泄漏
setState causing memory leak inside subject subscribe
我在第二次导航到 TestPage
时遇到错误。代码在第一次导航时工作正常,但在第二次导航时出现错误。
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.
我注意到如果删除 setinterval 块,则不会发生错误。
来自 observable 的数据在 Text
中反映良好,但我无法理解导致此错误的原因。因此我的问题是为什么 setState 在 observable subscribe 中不起作用?
export const testSubject = new Subject<any>();
setInterval(() => {
testSubject.next({ dest: 'any', msg: [] });
}, 2000);
function TestPage({ route, navigation }) {
const [data, setData] = useState<any[]>([]);
useFocusEffect(
useCallback(() => {
testSubject.subscribe(({ dest, msg }) => {
setData(msg);
});
return () => _cleanup();
}, []),
);
const _cleanup = () => {};
return (
<View>
<Text>{JSON.stringify(data)}</Text>
<Button
onPress={() => {
navigation.navigate('home');
}}
title="back"
/>
</View>
);
}
export default TestPage;
我不确定 useFocusEffect(useCallback(...))
到底是什么,但我假设它等同于常规 useEffect
。
您遇到的问题是您没有在组件卸载时清理对流的订阅。当 testSubject
上有新更新时,旧实例(已卸载)将在卸载组件上调用 setData()
,并且 React 会报错。
为什么 _cleanup
函数什么都不做?你只需要完成它:
useFocusEffect(
useCallback(() => {
const subscription = testSubject.subscribe(({ dest, msg }) => {
setData(msg);
});
return () => {
subscription.unsubscribe();
}
}, []),
);
这应该有效。
我在第二次导航到 TestPage
时遇到错误。代码在第一次导航时工作正常,但在第二次导航时出现错误。
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.
我注意到如果删除 setinterval 块,则不会发生错误。
来自 observable 的数据在 Text
中反映良好,但我无法理解导致此错误的原因。因此我的问题是为什么 setState 在 observable subscribe 中不起作用?
export const testSubject = new Subject<any>();
setInterval(() => {
testSubject.next({ dest: 'any', msg: [] });
}, 2000);
function TestPage({ route, navigation }) {
const [data, setData] = useState<any[]>([]);
useFocusEffect(
useCallback(() => {
testSubject.subscribe(({ dest, msg }) => {
setData(msg);
});
return () => _cleanup();
}, []),
);
const _cleanup = () => {};
return (
<View>
<Text>{JSON.stringify(data)}</Text>
<Button
onPress={() => {
navigation.navigate('home');
}}
title="back"
/>
</View>
);
}
export default TestPage;
我不确定 useFocusEffect(useCallback(...))
到底是什么,但我假设它等同于常规 useEffect
。
您遇到的问题是您没有在组件卸载时清理对流的订阅。当 testSubject
上有新更新时,旧实例(已卸载)将在卸载组件上调用 setData()
,并且 React 会报错。
为什么 _cleanup
函数什么都不做?你只需要完成它:
useFocusEffect(
useCallback(() => {
const subscription = testSubject.subscribe(({ dest, msg }) => {
setData(msg);
});
return () => {
subscription.unsubscribe();
}
}, []),
);
这应该有效。