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

React useReducer应用部署Netlify后计数异常求助

React useReducer多角色计数部署Netlify后异常问题分析

问题描述

我用React的useReducer实现多角色计数功能,本地运行正常,但部署到Netlify后出现计数异常:点击增减按钮时,控制台显示点击事件已触发,但count始终保持为0;只有快速点击递增按钮时count会短暂变成1,随后又回到0。改用useState统一管理状态就没问题,请问可能的原因是什么?

代码示例

import React, { useReducer } from 'react'
const initState = {
    barbarian: 0,
    archer: 0,
    giant: 0,
    goblin: 0,
    wizard: 0
}
const actionTypes = {
    increment: 'increment',
    decrement: 'decrement'
}
function reducer(count, action) {
switch (action.type) {

    case actionTypes.increment:
        {
            return {
                ...count,
                [action.name]: count[action.name]++
            }
        }

    case actionTypes.decrement:
        {
            return {
                ...count,
                [action.name]: count[action.name] > 0 ? count[action.name]-- : 0
            }
        }
    default:

        return count
}

}


export default function Count({ name, id }) {


const [count, dispatch] = useReducer(reducer, initState)
function increment() {
    setTimeout(() => {
        dispatch({
            type: actionTypes.increment,
            id: id,
            name: name
        })
        console.log(count[name])
        console.log(name)

    }, 500)

}

function decrement() {
    setTimeout(() => {
        dispatch({
            type: actionTypes.decrement,
            id: id,
            name: name
        })
    }, 500)
}

return (
    <div className='counter'>
        <button onClick={decrement} className='bg-info'>-</button>
        <p className='count'>{count[name]}</p>
        <button onClick={increment} className='bg-success'>+</button>
    </div>
)
}

问题原因与修复方案

核心原因

reducer中使用了自增/自减运算符(++/--),这会直接修改原state对象的属性值,违反了React状态不可变的原则。本地开发环境可能因代码优化未暴露问题,但Netlify的生产构建会严格遵循状态不可变性要求,导致状态更新逻辑失效:

  • count[action.name]++ 会先返回当前值,再修改原state的属性,这就导致返回的新对象中该属性值还是旧值,而原state被修改后,React无法正确识别状态变化,最终表现为计数不更新或回退。

修复步骤

  1. 修正reducer的状态更新逻辑,用值的计算替代自增/自减,保证状态不可变:
function reducer(count, action) {
  switch (action.type) {
    case actionTypes.increment:
      return {
        ...count,
        [action.name]: count[action.name] + 1
      };
    case actionTypes.decrement:
      return {
        ...count,
        [action.name]: count[action.name] > 0 ? count[action.name] - 1 : 0
      };
    default:
      return count;
  }
}
  1. 修正调试日志的问题:setTimeout中打印的count[name]是闭包捕获的旧状态值,无法反映更新后的状态。如果需要监听状态变化,改用useEffect:
import React, { useReducer, useEffect } from 'react'

// ... 其他代码不变

export default function Count({ name, id }) {
  const [count, dispatch] = useReducer(reducer, initState)

  useEffect(() => {
    console.log(count[name], name);
  }, [count, name])

  // ... 其他代码不变
}
  1. 确认状态作用域(可选):如果多个Count组件对应同一个角色的计数器,需要把useReducer提升到父组件,通过props传递count和dispatch,避免每个组件维护独立的状态实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 18:05:25