无法在未安装的组件主题提供程序上执行React状态更新

时间:2019-11-15 12:47:03

标签: javascript react-native themes

我需要帮助,因为出现以下错误:警告:无法在已卸载的组件上执行React状态更新。这是空操作,但它表明应用程序中发生内存泄漏。要解决此问题,请在componentWillUnmount方法中取消所有订阅和异步任务。在createCategory中(位于themeProvider.js:39)

/* Imports */
    import React, { useContext, useState, useEffect } from 'react';
    import AsyncStorage from '@react-native-community/async-storage';
    import THEMES from '@app/theme/themes.json';
    /* /Imports/ */

    const STORAGE_KEY = 'THEME_ID';
    const ThemeContext = React.createContext();

    /* Exports */
    export const ThemeContextProvider = ({ children }) => {
      const [themeID, setThemeID] = useState();

      useEffect(() => {
        (async () => {
          const storedThemeID = await AsyncStorage.getItem(STORAGE_KEY);
          if (storedThemeID) setThemeID(storedThemeID);
          else setThemeID(THEMES[1].key);
        })();
      }, []);

      return (
        <ThemeContext.Provider value={{ themeID, setThemeID }}>
          {!!themeID ? children : null}
        </ThemeContext.Provider>
      );
    };

    export function withTheme(Component) {
      function TargetComponent(props) {
        const { themeID, setThemeID } = useContext(ThemeContext);
        const getTheme = themeID => THEMES.find(theme => theme.key === themeID);
        const setTheme = themeID => {
          AsyncStorage.setItem(STORAGE_KEY, themeID);
          setThemeID(themeID);
        };

        return (
          <Component
            {...props}
            themes={THEMES}
            theme={getTheme(themeID)}
            setTheme={setTheme}
          />
        );
      }

      TargetComponent.navigationOptions = Component.navigationOptions;

      return TargetComponent;
      }
    /* /Exports/ */

2 个答案:

答案 0 :(得分:1)

如果您还不知道-您可以在useEffect挂钩的末尾返回一个函数。每当再次触发该效果时(例如,当其依赖项的值发生更改时),以及即将卸载组件时,都会调用该函数。因此,如果您有一个如下所示的useEffect钩子:

useEffect(() => {
  // logic here

  return () => {
    // clean up
  };
}, []); // no dependencies!

等效于此:

class SomeComponent extends React.Component {
  componentDidMount() {
    // logic here
  }

  componentWillUnmount() {
    // clean up
  }
}

因此,请在您的代码中添加以下内容:

useEffect(() => {
  let isCancelled = false;
  const fetchData = async () => {
    try {
      // fetch logic omitted...
      const data = await AsyncStorage.getItem(STORAGE_KEY);

      if (storedThemeID) setThemeID(storedThemeID);
      else setThemeID(THEMES[1].key);
    } catch (e) {
      throw new Error(e)
    }
  };

  fetchData();

  return () => {
    isCancelled = true;
  };
}, [themeID]);

答案 1 :(得分:0)

尝试

free