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

React函数组件无法使用setState?如何用useState正确更新状态?

核心问题梳理

  • React 函数式组件没有类组件的this.setState方法,你通过useState声明的状态,只能用对应返回的更新函数(也就是你代码里的setSum1、setSum2)修改。
  • 你当前的更新函数调用方式错误:useState返回的更新函数直接传入新状态值即可,不需要包裹成对象。你写的setSum1({sum1:parseFloat(sum1)})会把原本为数值类型的sum1改成对象,后续计算必然异常。
  • 不能直接给状态变量赋值:你代码里的sum1 = document.getElementById("result").value.slice(0, -1)是直接修改状态变量,React不会响应这个变更,所有状态修改必须走对应的更新函数。
  • 不要直接操作DOM修改输入框内容,React推荐用受控组件模式,把输入框的值绑定到状态,通过修改状态更新视图。

修正后可运行代码

import './App.css';
import React, { useState } from 'react';

function App() {
  // 存储第一个运算数
  const [num1, setNum1] = useState(0);
  // 存储运算符
  const [operator, setOperator] = useState('');
  // 存储输入框显示内容
  const [inputValue, setInputValue] = useState('');
  // 存储计算结果
  const [result, setResult] = useState(0);

  function handleClick(e) {
    const buttonVal = e.target.value;

    // 数字按钮逻辑
    if (!isNaN(buttonVal) || buttonVal === '.') {
      // 开头不要多余的0
      if (inputValue === '' && buttonVal === '0') return;
      setInputValue(prev => prev + buttonVal);
      return;
    }

    // 清空按钮
    if (buttonVal === 'clear') {
      setInputValue('');
      setNum1(0);
      setOperator('');
      setResult(0);
      return;
    }

    // 删除按钮
    if (buttonVal === 'Del') {
      setInputValue(prev => prev.slice(0, -1));
      return;
    }

    // 运算符按钮
    if (['+', '-', '*', '/', '%', '^'].includes(buttonVal)) {
      if (!inputValue) return;
      // 保存第一个运算数和运算符
      setNum1(parseFloat(inputValue));
      setOperator(buttonVal);
      // 清空输入框
      setInputValue('');
      return;
    }

    // 等于按钮
    if (buttonVal === '=') {
      if (!inputValue || !operator || !num1) return;
      const num2 = parseFloat(inputValue);
      let calcResult = 0;
      switch(operator) {
        case '+': calcResult = num1 + num2; break;
        case '-': calcResult = num1 - num2; break;
        case '*': calcResult = num1 * num2; break;
        case '/': calcResult = num1 / num2; break;
        case '%': calcResult = num1 % num2; break;
        case '^': calcResult = Math.pow(num1, num2); break;
        default: break;
      }
      setResult(calcResult);
      setInputValue(String(calcResult));
      setNum1(0);
      setOperator('');
      return;
    }
  }

  return (
    <div className="App">
      <div id="ans" className="answer">Ans = {result}</div>
      <input 
        type="text" 
        value={inputValue} 
        readOnly 
        placeholder="0" 
        className="inputid" 
        id="result"
      />
      <hr/> 
      <button className="opbut" value="+" onClick={handleClick}>+</button>
      <button className="opbut" value="-" onClick={handleClick}>-</button>
      <button className="opbut" value="*" onClick={handleClick}>×</button>
      <button className="opbut"  value="/" onClick={handleClick}>÷</button>
      <button className="calbut" value={0} onClick={handleClick}>0</button>
      <button className="calbut" value={1} onClick={handleClick}>1</button>
      <button className="calbut" value={2}  onClick={handleClick}>2</button>
      <button className="calbut" value={3} onClick={handleClick}>3</button>
      <button className="calbut" value={4} onClick={handleClick}>4</button>
      <button className="calbut" value={5} onClick={handleClick}>5</button>
      <button className="calbut" value={6} onClick={handleClick}>6</button>
      <button className="calbut" value={7} onClick={handleClick}>7</button>
      <button className="calbut" value={8} onClick={handleClick}>8</button>
      <button className="calbut"  value={9} onClick={handleClick}>9</button>
      <button className="opbut"  value="clear" onClick={handleClick}>C</button>
      <button className="opbut" value="Del" onClick={handleClick}>Del</button>
      <button className="opbut" value="%" onClick={handleClick}>%</button>
      <button className="opbut" value="^" onClick={handleClick}>y^</button>
      <button className="ansbut" value="=" onClick={handleClick}>=</button>
      <hr/>
      <div className="appName">A Simple React Calculator - Jayflo</div>
    </div>
  );
}

export default App;

主要修改点

  • 新增inputValue状态绑定输入框的值,完全替代直接操作DOM的逻辑
  • 新增operator状态存储选中的运算符,支持多种运算逻辑
  • 修正了状态更新函数的调用方式,所有状态修改都走对应的setXXX方法
  • 补充了删除、百分比、幂运算等原有按钮的对应逻辑
  • 优化了输入校验,避免开头多余0、空值运算等异常情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 14:09:05