为什么Fetch API无法提交useReducer更新后的最新状态?
你的问题出在useMemo的依赖配置和变量声明顺序上,具体原因和修复方案如下:
问题根源
- 变量声明顺序错误:你在声明
useMemo的时候,loginState和dispatch还没有通过useReducer创建,此时引用的是未定义/初始旧值。 useMemo依赖数组为空:useMemo只会在组件首次渲染时计算一次authContext,内部的signIn方法形成了闭包,永远捕获的是首次渲染时的loginState初始值(也就是email为null的状态),哪怕后续你通过dispatch更新了loginState,authContext也不会重新生成,所以提交的永远是旧数据。
修复步骤
- 把
useReducer的声明移到useMemo之前,确保useMemo可以拿到正确的dispatch和loginState引用。 - 在
useMemo的依赖数组中加入loginState,这样每当loginState更新时,authContext就会重新计算,signIn方法就能拿到最新的状态值。 - 可选优化:给
fetch加await,同时补充HTTP状态判断,避免接口报错无法捕获的问题。
修正后的App.js代码
import React from 'react'; import AuthContext from './context'; import ScreenA from './screenA'; // 组件名建议首字母大写,符合React规范 export default function App() { const initialLoginState = { email: null, }; const loginReducer = (prevState, action) => { switch (action.type) { case 'Email': return { ...prevState, email: action.Email, }; default: return prevState; // 建议加default分支处理未知action } }; // 先声明useReducer,再用useMemo const [loginState, dispatch] = React.useReducer( loginReducer, initialLoginState, ); const authContext = React.useMemo( () => ({ email: emailUser => { dispatch({type: 'Email', Email: emailUser}); }, signIn: async () => { try { const response = await fetch('FakeApi', { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ email: loginState.email, date: '2021-9-20', }), }); if (!response.ok) throw new Error('接口请求失败'); const data = await response.json(); // 后续处理登录成功逻辑 } catch (e) { console.log(e); } }, }), [loginState], // 加入loginState作为依赖 ); return ( <AuthContext.Provider value={authContext}> <ScreenA /> </AuthContext.Provider> ); }
内容的提问来源于stack exchange,提问作者Ali Mahmoudi
相关产品推荐
相关产品推荐

