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

React useReducer返回状态与日志值不一致,UID调度增量异常

问题原因

这个问题是开发环境下React StrictMode(严格模式)的行为和非纯函数reducer共同导致的:

  • React 18+的严格模式在开发环境中,会对reducer这类要求纯函数的逻辑执行两次,目的是提前检测非纯函数导致的异常问题
  • 你的reducer依赖了外部可变的全局变量uid,不属于纯函数:每次调用都会修改外部的uid值,两次调用就会让uid累加两次
  • 同时严格模式会自动静默第二次reducer调用产生的console.log输出,所以你只能看到第一次调用的打印结果,但是实际采用的是第二次调用后的返回值,自然就出现了打印值和渲染值差1、每次累加2的情况

你用useRef存uid也会有同样问题,因为ref的值是可变的,reducer依赖ref的话依然不属于纯函数,严格模式下两次调用同样会修改两次ref的值。

这个问题只会在开发环境出现,生产环境下严格模式不会重复调用reducer,但不建议依赖这个行为,保持reducer是纯函数是React的官方最佳实践。

修复方案

将uid存入reducer管理的state中,保证reducer是纯函数,状态变更完全由传入的state和action决定即可:

import React, { useReducer }  from "react"

function reducer(state, action) {
    switch (action.type) {
        case "increment":
            const newUid = state.uid + 1
            return {
                uid: newUid,
                text: `current UID is ${newUid}!`
            }
        default:
            return state
    }
}

function TestComponent() {
    const [state, dispatch] = useReducer(reducer, {
        uid: 0,
        text: "not clicked yet"
    })
    return <button onClick={() => dispatch({ type: "increment" })}>{state.text}</button>
}

export default TestComponent

这个写法下reducer是纯函数,两次调用返回的结果完全一致,严格模式的重复调用不会产生任何异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 04:36:04