useEffect 清理功能在 React Native 中不起作用
Posted
技术标签:
【中文标题】useEffect 清理功能在 React Native 中不起作用【英文标题】:useEffect cleanup function not working in 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;
【问题讨论】:
【参考方案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 对我大喊大叫,说应该清除所有订阅和异步任务以上是关于useEffect 清理功能在 React Native 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章
socket.io useEffect 清理函数 react
react 钩子中的 useEffect 执行顺序及其内部清理逻辑是啥?
删除组件后如何清理react js中的useEffect函数