【问题标题】:useEffect cleanup function not working in React NativeuseEffect 清理功能在 React Native 中不起作用
【发布时间】:2021-10-31 05:41:25
【问题描述】:

我正在尝试从 Expo 的 SecureStore 获取令牌,然后发送一个操作。

我正在使用 useEffect 以便在组件首次渲染时检查是否有可以使用的令牌。

useEffect(() => {
let mounted = true;

SecureStore.getItemAsync('token').then((token) =>
  token ? dispatch({ type: 'signin', payload: token }) : null
);

return () => (mounted = false);
}, []);

但是,我无法摆脱:

无法对未安装的组件执行 React 状态更新。这是 无操作,但它表明您的应用程序中存在内存泄漏。修理, 在 useEffect 清理中取消所有订阅和异步任务 功能

enter image description here

根据要求提供更多代码:

import React, { useReducer, createContext, useEffect } from 
'react';
import * as SecureStore from 'expo-secure-store';
import forumApi from '../api/forumApi';

export const Context = createContext();

const reducer = (state, action) => {
switch (action.type) {
case ('signup', 'signin'):
  return { ...state, token: action.payload };
case 'error': {
  return { token: undefined, errorMessage: action.payload };
}
default:
  return state;
 }
};

const AuthProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, {
token: undefined,
errorMessage: '',
 });

useEffect(() => {
let mounted = true;

const runAsync = async () =>
  await SecureStore.getItemAsync('token').then((token) =>
    token ? dispatch({ type: 'signin', payload: token }) : null
  );

runAsync();

return () => (mounted = false);
}, []);

const signup = async (fullName, email, password, passwordConfirm) 
=> {
try {
  const res = await forumApi.post('/api/v1/users/signup', {
    fullName,
    email,
    password,
    passwordConfirm,
  });

  const { token } = res.data;
  await SecureStore.setItemAsync('token', token);
  dispatch({ type: 'signup', payload: token });
} catch (err) {
  dispatch({
    type: 'error',
    payload: 'We could not register you. Please try with 
 different email.',
  });
 }
 };

 const signin = async (email, password) => {
 try {
  const res = await forumApi.post('/api/v1/users/signin', {
    email,
    password,
  });

  const { token } = res.data;
  await SecureStore.setItemAsync('token', token);
  dispatch({ type: 'signin', payload: token });
} catch (err) {
  dispatch({
    type: 'error',
    payload: 'We could not log you in. Please try again.',
  });
 }
 };

const signinGoogle = async (token, fullName, email, photo) => {
try {
  const res = await forumApi.post('/api/v1/users/auth/google', {
    fullName,
    email,
    photo,
  });

  await SecureStore.setItemAsync('token', token);
  dispatch({ type: 'signup', payload: token });
} catch (err) {
  dispatch({
    type: 'error',
    payload: 'We could not register you. Please try with different email.',
  });
}
};

return (
<Context.Provider
  value={{ state, signup, signin, signinGoogle, tryLocalSignin }}
>
  {children}
</Context.Provider>
 );
 };

export default AuthProvider;

【问题讨论】:

    标签: reactjs react-native expo


    【解决方案1】:

    @florian22 所以看起来你正在尝试更新提供者级别的状态。为了更新上下文的状态,您必须在提供者内部。 useEffect 必须在内部节点上。

    查看示例:

    const App = ({children}) => {
    
        useEffect(() => {
         const runAsync = async () => {
         const token = await SecureStore.getItemAsync('token');
    
         if(token) dispatch({ type: 'signin', payload: token });
         }
    
         runAsync();
         }, []);
    
      return (<View>{children}</View>);
      }
    
    const MainApp = ({children}) => {
    
    return (
    <AuthProvider>
     <App>
      {children}
     </App>
    </AuthProvider>
    }

    【讨论】:

    • 谢谢,但同样的问题。我正在使用 then 语法,所以这就是我不等待的原因。我正在使用mounted 变量,以便我可以清除订阅和异步任务。就是这么说的,我附上了截图
    • @florian22 你能把你所有的代码贴在页面上吗?另外,如果您还没有看到它,请查看我的修改代码。异步运行您的方法并等待它应该会阻止它尝试更新已卸载的组件。
    • 不幸的是,异步运行它然后等待不工作。我已经添加了上面的所有代码
    • @florian22 请查看更新后的代码。您只能在 AuthProvider 中更新您的状态。不能在同一级别上完成。
    • 我明白了。我调整了代码,现在不再出现错误。谢谢!
    【解决方案2】:

    不需要使用mounted 变量。够了

    useEffect(() => {
      SecureStore.getItemAsync("token").then((token) =>
        token ? dispatch({ type: "signin", payload: token }) : null
      );
    }, []);
    

    【讨论】:

    • 对,这是我最初的猜测,但 React Native 对我大喊大叫,说应该清除所有订阅和异步任务
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-07
    • 1970-01-01
    • 2021-12-24
    • 2021-04-09
    • 1970-01-01
    • 2021-03-24
    • 1970-01-01
    相关资源
    最近更新 更多