【问题标题】:Can't perform a React state update on an unmounted component theme provider无法在未安装的组件主题提供程序上执行 React 状态更新
【发布时间】:2020-03-11 15:04:06
【问题描述】:

我需要帮助,因为我收到以下错误:警告:无法对未安装的组件执行 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/ */

【问题讨论】:

    标签: javascript react-native themes


    【解决方案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]);
    

    【讨论】:

    【解决方案2】:

    试试这个

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

    【讨论】:

      猜你喜欢
      • 2021-08-13
      • 2020-09-04
      • 2020-08-03
      • 2021-07-01
      • 2020-11-21
      • 2019-11-09
      • 2019-05-30
      • 2021-05-30
      相关资源
      最近更新 更多