简体   繁体   English

如何在 react native 中使用效果清理 function?

[英]How to useEffect cleanup function in react native?

Warning: Can't perform a React state update on an unmounted component.警告:无法对未安装的组件执行 React state 更新。 This is a no-op, but it indicates a memory leak in your application.这是一个无操作,但它表明您的应用程序中存在 memory 泄漏。 To fix, cancel all subscriptions and asynchronous tasks in %s.%s, a useEffect cleanup function,要修复,请取消 %s.%s 中的所有订阅和异步任务,useEffect 清理 function,

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>
  );
}

You should always clear setTimeout s setInterval s on unmount.您应该始终在卸载时清除setTimeout s setInterval s。

useEffect(() => {
  const timeout = setTimeout(() => {
    setIsLoading(false);
  }, 1000);

  return () => clearTimeout(timeout);
}, []);

You received this warning because setTimeout was still on process even of the component was unmounted.您收到此警告是因为即使组件已卸载, setTimeout仍在处理中。

The syntax is very easy:语法非常简单:

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

To prevent component not updating state when un-mounted you can use useRef and cleanup function为了防止组件在卸载时不更新 state,您可以使用useRef和清理 function

const mounted = useRef(false);

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

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

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

Solution解决方案

Using Axios:使用 Axios:

import axios from 'axios';

Component:零件:

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;

Above implementation is per the original Axios docs, read here to understand in detail.上面的实现是根据原始的 Axios 文档,阅读这里详细了解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM