如何在React Native中使用效果清理功能?

时间:2020-06-12 17:48:59

标签: reactjs react-native react-redux react-router

警告:无法在已卸载的组件上执行React状态更新。这是空操作,但它表明应用程序中发生内存泄漏。要修复,请取消%s。%s(一种useEffect清理功能)中的所有订阅和异步任务,

const Drawer = createDrawerNavigator();

const App = () => {
  const [isLoading, setIsLoading] = React.useState(true);
  const [userToken, setUserToken] = React.useState(null);

  const authContext = React.useMemo(() => ({
    SignIn: () => {
      setUserToken('qwertyuiop');
      setIsLoading(false);
    },
    SignOut: () => {
      setUserToken(null);
      setIsLoading(false);
    },
    SignUp: () => {
      setUserToken('qwe');
      setIsLoading(false);
    },
  }));

  useEffect(() => {
    setTimeout(() => {
      setIsLoading(false);
    }, 1000);
  }, []);

  if (isLoading) {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <ActivityIndicator size="large" />
      </View>
    );
  }

  console.log("userToken", userToken)
  console.log("authContext", authContext)
  return (
    <AuthContext.Provider value={authContext}>
      <NavigationContainer>
        {userToken !== null ? (
          <Drawer.Navigator drawerContent={props => <DrawerContent {...props} />}>
            <Drawer.Screen name="HomeDrawer" component={MainTabScreen} />
            <Drawer.Screen name="Support" component={SupportScreen} />
            <Drawer.Screen name="Setting" component={SettingScreen} />
            <Drawer.Screen name="Bookmark" component={BookmarkScreen} />
          </Drawer.Navigator>
        )
          :
          <RootStackScreen />
        }
      </NavigationContainer>
    </AuthContext.Provider>
  );
}

4 个答案:

答案 0 :(得分:1)

卸载时,您应始终清除'check'setTimeout

setInterval

您收到此警告是因为useEffect(() => { const timeout = setTimeout(() => { setIsLoading(false); }, 1000); return () => clearTimeout(timeout); }, []); 仍在处理中,即使已卸下组件。

答案 1 :(得分:0)

语法非常简单:

useEffect(() => {
    setTimeout(() => {
      setIsLoading(false);
    }, 1000);
    return () => someCleanUp() // your cleanup function
}, []);

答案 2 :(得分:0)

为防止组件在卸载时不更新状态,可以使用useRef和清理功能

const mounted = useRef(false);

useEffect(() => {
    mounted.current = true;

    setTimeout(() => {
      if (mounted.current) {
        setIsLoading(false);
      }
    }, 1000);

    return function cleanup() {
      mounted.current = false;
    }
}, []);

答案 3 :(得分:0)

解决方案

使用Axios:

import axios from 'axios';

组件:

const Home: React.FC = () => {

let cancelToken: any = axios.CancelToken;
let source = cancelToken.source();

useEffect(() => {
    (async () => {

      try {
        const data = await axios.get("https://<you-api-url>", {
            cancelToken: source.token
        });
        
      }catch (error) {
        if (axios.isCancel(error)) {
          console.log('Request canceled', error.message);
        } else {
          // handle error
          console.log(error);
        }
      }

    })();

    return () => {
      //when the component unmounts
      console.log("component unmounted");

      // cancel the request (the message parameter is optional)
      source.cancel('Operation canceled by the user.');
    }
}, []); //End UseEffect

return ();

};

export default Home;

以上实现是根据原始Axios文档进行的,请阅读here以了解详细信息。