首页 > 解决方案 > setState 导致主题订阅内的内存泄漏

问题描述

我在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 在可观察订阅中不起作用?

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;

标签: reactjsreact-nativerxjsreact-navigation

解决方案


我不确定到底是什么useFocusEffect(useCallback(...)),但我会假设它相当于普通的useEffect.

您遇到的问题是,当组件卸载时,您没有清理对流的订阅。当 有新的更新时testSubject,旧实例(已卸载)将调用setData()卸载组件,并且 react 会抱怨。

为什么那个_cleanup函数什么都不做?你只需要完成它:

    useFocusEffect(
        useCallback(() => {
            const subscription = testSubject.subscribe(({ dest, msg }) => {
                setData(msg);
            });
            return () => {
                subscription.unsubscribe();
            }
        }, []),
    );

这应该有效。


推荐阅读