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

React useReducer计算器数字不显示问题排查求助

问题排查:React useReducer计算器数字无法显示

问题场景

使用React useReducer开发计算器,数字/操作按钮已封装为独立组件,按钮可正常渲染,但点击后数字无法显示在计算器面板上,聚焦ACTIONS.ADD_DIGIT相关逻辑排查。

核心代码

App组件(含Reducer逻辑)

import React , {useReducer ,useState}from "react";
import ButtonDigit from "./ButtonDigit";
import ButtonOperation from "./ButtonOperation";
import "./style.css"

export const ACTIONS = {
  ADD_DIGIT : 'add-digit',
  DELETE_DIGIT: 'delete-digit',
  CLEAR: 'clear',
  CHOOSE_OPERATION: 'choose-operation',
  EVALUATION: 'evaluation'
}

function reducer (state, action) { 
   switch(action.type){
    case ACTIONS.ADD_DIGIT: 
      return {...state, currentOperand: `${state.currentOperand || ""}${action.payload}`}  
    case ACTIONS.DELETE_DIGIT:
      return state
    case ACTIONS.CLEAR:
      return {currentOperand: 0}
    case ACTIONS.CHOOSE_OPERATION:
      return state
    case ACTIONS.EVALUATION:
      return state
    default:
      return state
   }
}
export default function App() {
  const [{prevOperand=null, currentOperand =0, operation=null}, dispatch] = useReducer(reducer,{})
  return (
    <div className="calculator-grid">
      <div className="output">
        <div className="prev-operand">{prevOperand} {operation}</div>
        <div className="current-operand">{currentOperand}</div>
      </div>
        <button className="span-two">AC</button>
        <button>DEL</button>
        <ButtonOperation operation={'/'} dispatch={dispatch}/>
        <ButtonDigit number="1" dispatch={dispatch}/>
        <ButtonDigit number="2" dispatch={dispatch}/>
        <ButtonDigit number="3" dispatch={dispatch}/>
        <ButtonOperation operation={'*'} dispatch={dispatch}/>
        <ButtonDigit number="4" dispatch={dispatch}/>
        <ButtonDigit number="5" dispatch={dispatch}/>
        <ButtonDigit number="6" dispatch={dispatch}/>
        <ButtonOperation operation={'+'} dispatch={dispatch}/>
        <ButtonDigit number="7" dispatch={dispatch}/>
        <ButtonDigit number="8" dispatch={dispatch}/>
        <ButtonDigit number="9" dispatch={dispatch}/>
        <ButtonOperation operation={'-'} dispatch={dispatch}/>
        <ButtonOperation operation={'.'} dispatch={dispatch}/>
        <ButtonDigit number="0" dispatch={dispatch}/>
        <button className="span-two">=</button>
    </div>
  );
}

ButtonDigit组件

import React from 'react'
import ACTIONS from './App'

export default function ButtonDigit({number,dispatch}) {
  return (
    <>
      <button onClick={() => dispatch({type:ACTIONS.ADD_DIGIT , payload:number})}>
        {number}
      </button>
    </>
  )
}

问题根源

  1. ACTIONS导入错误:在ButtonDigit组件中,ACTIONS是App组件中用export const导出的具名常量,但使用了默认导入import ACTIONS from './App',导致ACTIONS实际指向App组件本身(默认导出的是App函数),而非定义的ACTIONS对象。点击按钮时dispatch的type为undefined,reducer无法匹配到ACTIONS.ADD_DIGIT分支,状态不会更新。

  2. 初始state默认值不一致:useReducer初始state为{},解构时给currentOperand设了默认值0,但第一次调用ADD_DIGIT时,reducer中的state.currentOperand是undefined,虽用|| ""处理,但初始渲染的currentOperand是0,第一次点击后会变成"01"这类字符串,不符合常规计算器的输入逻辑。

修复方案

修复ButtonDigit的ACTIONS导入

将ButtonDigit中的导入改为具名导入:

import React from 'react'
// 改为具名导入匹配导出方式
import { ACTIONS } from './App'

export default function ButtonDigit({number,dispatch}) {
  return (
    <>
      <button onClick={() => dispatch({type:ACTIONS.ADD_DIGIT , payload:number})}>
        {number}
      </button>
    </>
  )
}

优化初始state(可选但推荐)

修改App中useReducer的初始state,统一状态默认值:

// 直接在初始state中设置默认值,避免解构和reducer中的状态不一致
const [{prevOperand, currentOperand, operation}, dispatch] = useReducer(reducer, {
  prevOperand: null,
  currentOperand: "",
  operation: null
})

// 同时调整reducer的ADD_DIGIT分支,优化输入逻辑(避免重复输入0)
case ACTIONS.ADD_DIGIT: 
  if (action.payload === "0" && state.currentOperand === "0") return state
  return {...state, currentOperand: `${state.currentOperand}${action.payload}`}  

验证

修复后点击数字按钮,reducer会正确匹配ADD_DIGIT类型,更新currentOperand值,计算器面板即可正常显示点击的数字。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 00:40:19