React中使用useReducer实现计数器时增减操作出现NaN问题排查求助
问题分析与解决方案
嘿,我懂你遇到NaN问题的烦躁——咱们直接揪出根源,让计数器正常跑起来!
核心问题:State结构不匹配
你在初始化useReducer的state时,把初始计数存在了initialCount属性里:
{ initialCount: initialCount }
但在reducer逻辑和Counter组件中,你访问的却是state.count。这就导致初始状态下state.count是undefined,当你执行加减操作时,undefined + 1或者undefined -1都会得到NaN,后续所有操作都会基于这个NaN,结果自然一直是NaN。
修复步骤
只需要把初始化的state结构改成{ count: initialCount },让reducer和组件访问的属性保持一致:
// 修改useReducer的初始state const [state, dispatch] = React.useReducer( (state, action) => { const change = action.step ?? step switch (action.type) { case 'increment': { return { ...state, count: state.count + change } } case 'decrement': { return { ...state, count: state.count - change } } default: { throw new Error(`Unhandled action type:${action.type}`) } } }, { count: initialCount } // 这里把initialCount改成count )
额外优化建议
useCallback的依赖简化:dispatch是useReducer返回的稳定引用,不需要放进useCallback的依赖数组里,所以可以写成:
const increment = React.useCallback(() => dispatch({ type: 'increment' }), []) const decrement = React.useCallback(() => dispatch({ type: 'decrement' }), [])
这样能避免不必要的函数重复创建。
- State结构一致性:保持state的属性名统一,后续维护起来会更清晰。
修复后的完整代码
import * as React from 'react'; const CounterContext = React.createContext(); function CounterProvider({ step = 1, initialCount = 0, ...props }) { const [state, dispatch] = React.useReducer( (state, action) => { const change = action.step ?? step switch (action.type) { case 'increment': { return { ...state, count: state.count + change } } case 'decrement': { return { ...state, count: state.count - change } } default: { throw new Error(`Unhandled action type:${action.type}`) } } }, { count: initialCount } // 修正此处的state属性名 ) // 简化useCallback的依赖 const increment = React.useCallback(() => dispatch({ type: 'increment' }), []) const decrement = React.useCallback(() => dispatch({ type: 'decrement' }), []) const value = { increment, decrement, state } return <CounterContext.Provider value={value} {...props} /> } function useCounter() { const context = React.useContext(CounterContext) if (context === undefined) { throw new Error('useCounter must be used within CounterProvider') } return context } function Counter() { const { state, increment, decrement } = useCounter(); console.log(state, 'inc ', increment, 'dec ', decrement) return ( <div> <button onClick={decrement}>-</button> <button onClick={increment}>+</button> <div>Current Count: {state.count}</div> </div> ) } function App() { return ( <CounterProvider> <Counter /> </CounterProvider> ) } export default App
这样修改后,计数器的加减操作就能正常计算数值,不会再出现NaN了!
内容的提问来源于stack exchange,提问作者Fares_Essayeh
相关产品推荐
相关产品推荐

