从 UseEffect 获取内存泄漏错误以响应本机导航身份验证流程

发布于 2025-01-20 13:21:33 字数 3146 浏览 1 评论 0原文

我正在尝试设置反应本机导航身份验证流程,但出现如下错误;

<块引用>

警告:无法对已卸载的组件执行 React 状态更新。这是一个空操作,但它表明应用程序中存在内存泄漏。要修复此问题,请取消 useEffect 清理函数中的所有订阅和异步任务。

该错误很可能是由此处的代码引起的。我之前修复了它,同时从这里得到了不同的错误,但现在它给出了内存泄漏错误。

  React.useEffect(() => {
    // Fetch the token from storage then navigate to our appropriate place
    const bootstrapAsync = async () => {
      let userToken;
      try {
        userToken = await SecureStore.getItemAsync(LOGIN_KEY);
        // IF USER ALREADY LOGGED IN CREATE NEW TOKEN TO KEEP USER LOGGED IN
        if(userToken!==null){
          let email = await SecureStore.getItemAsync(USER_NAME)
          let loginPassword = await SecureStore.getItemAsync(USER_PASSWORD)
          authContext.signIn({email,loginPassword})
                      .then(res=> {
                           if(res.response.status ==401){
                              authContext.signOut()
                              }
                            console.log(res)
                      })
                      .catch(err=>{ console.log(err)})
        }
        console.log("userTokennn ", userToken )
      } catch (e) {
        // Restoring token failed
        console.log("boostrapError", e)
      }
      // After restoring token, we may need to validate it in production apps
      // This will switch to the App screen or Auth screen and this loading
      // screen will be unmounted and thrown away.
      dispatch({ type: 'RESTORE_TOKEN', token: userToken });
    };
     bootstrapAsync();
  }, []);

另外,我尝试使用清理功能,但它没有像这样工作;

};
    return ()=> bootstrapAsync();
  }, []);

其余的代码在这里;

const authContext = React.useMemo(
    () => ({
      signIn: async (data) => {
        // In a production app, we need to send some data (usually username, password) to server and get a token
        // We will also need to handle errors if sign in failed
        // After getting token, we need to persist the token using `SecureStore`
        // In the example, we'll use a dummy token
         //SEND LOGIN INFO TO SERVER
       return await postSignIn(data.email, data.loginPassword)
        .then(async(res)=>{
            token = res.data.token
            await SecureStore.setItemAsync(LOGIN_KEY, token);
            await SecureStore.setItemAsync(USER_NAME, data.email )
            await SecureStore.setItemAsync(USER_PASSWORD, data.loginPassword )
            dispatch({ type: 'SIGN_IN', token: token });
        })
        .catch((err)=>{ console.log("sign in error", err); return err})
      },
    
      signOut: () => dispatch({ type: 'SIGN_OUT' }),
      signUp: async (data) => {
        // In a production app, we need to send user data to server and get a token
        // We will also need to handle errors if sign up failed
        // After getting token, we need to persist the token using `SecureStore`
        // In the example, we'll use a dummy token

        dispatch({ type: 'SIGN_IN', token: 'dummy-auth-token' });
      },
    }),
    []
  
  );

I am trying to set react native navigation auth flow but I give an error like;

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.

Most likely the error is caused by the codes here. I fixed it before while getting a different error from here, but now it gives a memory leak error.

  React.useEffect(() => {
    // Fetch the token from storage then navigate to our appropriate place
    const bootstrapAsync = async () => {
      let userToken;
      try {
        userToken = await SecureStore.getItemAsync(LOGIN_KEY);
        // IF USER ALREADY LOGGED IN CREATE NEW TOKEN TO KEEP USER LOGGED IN
        if(userToken!==null){
          let email = await SecureStore.getItemAsync(USER_NAME)
          let loginPassword = await SecureStore.getItemAsync(USER_PASSWORD)
          authContext.signIn({email,loginPassword})
                      .then(res=> {
                           if(res.response.status ==401){
                              authContext.signOut()
                              }
                            console.log(res)
                      })
                      .catch(err=>{ console.log(err)})
        }
        console.log("userTokennn ", userToken )
      } catch (e) {
        // Restoring token failed
        console.log("boostrapError", e)
      }
      // After restoring token, we may need to validate it in production apps
      // This will switch to the App screen or Auth screen and this loading
      // screen will be unmounted and thrown away.
      dispatch({ type: 'RESTORE_TOKEN', token: userToken });
    };
     bootstrapAsync();
  }, []);

Also, I tried to use clean up function but it didn't work like this;

};
    return ()=> bootstrapAsync();
  }, []);

The rest of the codes are here;

const authContext = React.useMemo(
    () => ({
      signIn: async (data) => {
        // In a production app, we need to send some data (usually username, password) to server and get a token
        // We will also need to handle errors if sign in failed
        // After getting token, we need to persist the token using `SecureStore`
        // In the example, we'll use a dummy token
         //SEND LOGIN INFO TO SERVER
       return await postSignIn(data.email, data.loginPassword)
        .then(async(res)=>{
            token = res.data.token
            await SecureStore.setItemAsync(LOGIN_KEY, token);
            await SecureStore.setItemAsync(USER_NAME, data.email )
            await SecureStore.setItemAsync(USER_PASSWORD, data.loginPassword )
            dispatch({ type: 'SIGN_IN', token: token });
        })
        .catch((err)=>{ console.log("sign in error", err); return err})
      },
    
      signOut: () => dispatch({ type: 'SIGN_OUT' }),
      signUp: async (data) => {
        // In a production app, we need to send user data to server and get a token
        // We will also need to handle errors if sign up failed
        // After getting token, we need to persist the token using `SecureStore`
        // In the example, we'll use a dummy token

        dispatch({ type: 'SIGN_IN', token: 'dummy-auth-token' });
      },
    }),
    []
  
  );

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

屋檐 2025-01-27 13:21:33

由于 api 调用的异步性质,有些情况下它们会在组件卸载后完成,例如用户访问页面,数据开始加载,但在加载完成之前,用户已导航到另一个页面。
这里有一些解决方案。

  1. 您可以跟踪正在安装的组件的状态。
const [mounted, setMounted] = useState(true);

React.useEffect(() => {
  if (mounted) {
    bootstrapAsync();
  }

  return () => {
    setMounted(false);
  };
}, []);
  1. 使用诸如来自react-use库的 useAsync 之类的东西,它负责处理这个问题。

Due to the async nature of api calls, there are cases when they will complete after component has been unmounted, e.g. user visits a page, the data starts loading, but before it's finished loading, the user has navigated to another page.
There are a few solutions here.

  1. You can keep track of the component being mounted on the state.
const [mounted, setMounted] = useState(true);

React.useEffect(() => {
  if (mounted) {
    bootstrapAsync();
  }

  return () => {
    setMounted(false);
  };
}, []);
  1. Use smth like useAsync from react-use library, which takes care of this.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文