You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么React Context中使用useReducer无法更新状态?

问题修复方案

核心问题原因

  • useMemo 依赖项缺失:你包裹 authContext 的 useMemo 依赖数组为空,导致 authContext 仅在App组件首次渲染时创建一次,后续无论状态怎么更新,authContext 内的方法永远引用首次渲染时的初始 loginState(email 固定为 null),不会同步最新状态。
  • 变量声明顺序错误:你先创建 authContext 时用到了 dispatch 和 loginState,但这两个变量是在后续才通过 useReducer 声明的,初始化阶段会拿到未定义值,逻辑顺序有误。
  • React状态更新是异步机制:dispatch 触发reducer更新状态是批量异步处理的,调用dispatch后立刻打印loginState.email,拿到的必然是更新前的旧值,属于React正常运行机制。
  • 组件命名不规范:screenA 首字母小写,React会将其识别为原生HTML标签而非自定义组件,可能引发渲染异常。

修复后代码

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分支兜底避免异常
    }
  };

  // 调整顺序:先声明useReducer,再创建authContext
  const [loginState, dispatch] = React.useReducer(
    loginReducer,
    initialLoginState,
  );

  const authContext = React.useMemo(
    () => ({
      email: emailUser => {
        dispatch({type: 'Email', Email: emailUser});
        // 此处无法打印更新后的值,可通过useEffect监听loginState查看最新状态
      },
      signIn: async () => {
        try {
          await fetch('FakeApi', { // 新增await处理异步请求
            method: 'POST',
            headers: {
              Accept: 'application/json',
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({
              email: loginState.email,
              date: '2021-9-20',
            }),
          });
        } catch (e) {
          console.log(e);
        }
      },
    }),
    [loginState], // 加入loginState作为依赖,状态更新时同步刷新context
  );

  return (
    <AuthContext.Provider value={authContext}>
      <ScreenA />
    </AuthContext.Provider>
  );
}

screenA.js(文件名同步改为ScreenA.js)

import React from 'react';
import { View, Button } from 'react-native'; // 补全原生组件导入
import {AuthContext} from './context';

function ScreenA() {
 const {email,signIn} = React.useContext(AuthContext);
 return (
   <View style={{marginTop: 150}}>
     <Button
       title="sent email"
       onPress={() => {
         email('example@gmail.com');
       }}
     />
     <Button
       title="signIn"
       onPress={() => {
         signIn();
       }}
     />
   </View>
 );
}

export default ScreenA;

额外调试建议

如果需要查看email更新后的最新值,可以在App组件中添加监听逻辑:

React.useEffect(() => {
  console.log('最新email值:', loginState.email);
}, [loginState.email]);

内容的提问来源于stack exchange,提问作者Ali Mahmoudi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 23:12:05