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

React计算器点击运算符报too many renders错误如何解决?

问题根因

你遇到的无限重渲染报错和运算符不显示问题,根源是将状态更新逻辑直接写在了组件渲染主流程中:

  • 组件函数主体(return语句之前的代码)属于渲染逻辑,每次组件重渲染都会逐行执行
  • 当你点击+按钮调用sum()修改operation为'+'后,组件触发重渲染,此时operation === "+"的判断成立,调用setValue()修改状态
  • 状态更新又会触发新一轮重渲染,再次执行setValue(),陷入无限循环,就抛出了too many re-renders错误

为什么clear函数能正常运行?

调用clear()时会把operation设为空字符串,所有判断运算类型的if分支都不会触发,不会执行setValue()更新状态,也就不会进入无限重渲染循环。

修复方案

你可以把自动运算的逻辑放到useEffect钩子中,只在依赖的firstValue、secondValue、operation变化时才执行运算,避免每次渲染都触发状态更新:

import React, { useState, useEffect } from "react";

const Calculator = () => {
  const [firstValue, setFirstValue] = useState('')
  const [secondValue, setSecondValue] = useState('')
  const [operation, setOperation] = useState('')
  const [value, setValue] = useState('')

  function sum() {
    setOperation('+')
  }
  
  // 其余运算符逻辑可以参照sum封装为单独函数,或者统一传参处理
  function sub() {
    setOperation('-')
  }
  function mul() {
    setOperation('x')
  }
  function div() {
    setOperation('/')
  }

  function clear() {
    setFirstValue('')
    setSecondValue('')
    setOperation('')
    setValue('')
  }
  
  // 运算逻辑移入useEffect,仅依赖项变化时执行
  useEffect(() => {
    // 两个输入框都有值才执行运算,避免NaN
    if (!firstValue || !secondValue || !operation) return
    const num1 = parseInt(firstValue)
    const num2 = parseInt(secondValue)
    switch(operation) {
      case '+':
        setValue(num1 + num2)
        break
      case '-':
        setValue(num1 - num2)
        break
      case 'x':
        setValue(num1 * num2)
        break
      case '/':
        setValue(num2 === 0 ? '除数不能为0' : num1 / num2)
        break
      default:
        return
    }
  }, [operation, firstValue, secondValue])

  return (
    <div className="calculator">
      <div data-testid="name">Calculator</div>

      <div data-testid="display" className="display">{firstValue} {operation} {secondValue} {value ? `= ${value}` : ''}</div>

      <div className="number-inputs">
        <input onChange={(e) => setFirstValue(e.target.value)} data-testid="num1" id="num1" type="number"></input>

        <div data-testid="selected-operation">{operation}</div>
        <input onChange={(e) => setSecondValue(e.target.value)} data-testid="num2" id="num2" type="number"></input>
      </div>

      <div className="operation-selectors">
        <button onClick={sum} data-testid="add">+</button>
        <button onClick={sub} data-testid="sub">-</button>
        <button onClick={mul} data-testid="mul">x</button>
        <button onClick={div} data-testid="div">/</button>
      </div>

      <div className="options">
        <button onClick={clear} data-testid="clear" className="clear">
          Clear
        </button>
        <button data-testid="calc">Calculate</button>
      </div>

      <div data-testid="error" id="error" className="error"></div>
    </div>
  );
};

export default Calculator;

补充说明

你不需要额外处理类组件的挂载逻辑,useEffect已经覆盖了函数式组件的挂载、更新、卸载生命周期场景,本次问题和挂载逻辑无关。
另外点击事件的写法不用额外传e调用preventDefault,按钮的默认点击行为不会影响业务逻辑,直接写onClick={sum}即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 17:45:01