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

React计算器calculate函数报错:Cannot read properties of undefined (reading 'length')

React计算器点击等号触发TypeError问题排查与修复

错误核心原因

点击等号按钮时触发TypeError: Cannot read properties of undefined (reading 'length'),同时控制台无日志输出,根源有两个:

  1. 参数未传递:等号点击事件中调用calculate()时未传入组件的storeArr状态,导致函数内的storeArr参数为undefined,访问storeArr.length直接报错。
  2. 无限递归:calculate函数内部执行console.log(calculate(storeArr)),会无限递归调用自身,不仅无法输出日志,还会引发栈溢出,阻断正常执行流程。

其他潜在问题

  • click函数中重复调用setActiveKey(selector),且直接依赖activeKey旧值判断(if (activeKey !== "=")),由于React状态更新是异步的,这里的判断逻辑可能不符合预期。
  • 计算完成后未将结果同步更新到组件状态,无法在界面展示计算结果。

修复步骤

  1. 传递正确参数:等号按钮点击时,传入组件的storeArr状态:
    onClick={() => {
      if (i.text === "=") {
        calculate(storeArr);
      } else {
        click(i.text);
      }
    }}
    
  2. 移除递归调用:将calculate内的递归调用改为打印最终结果:
    // 替换 console.log(calculate(storeArr));
    console.log("计算结果:", storeArr[0]);
    
  3. 修复click函数逻辑:使用函数式更新获取最新状态,避免重复setState:
    function click(selector) {
      setActiveKey(selector);
      if (selector !== "=") { // 直接判断传入的selector,而非依赖可能过期的activeKey
        setStoreArr(prev => [...prev, selector]);
      }
    }
    
  4. 同步计算结果到状态:计算完成后更新storeArr和activeKey,展示结果:
    function calculate(inputArr) {
      // 先复制一份数组,避免直接修改原状态数组
      const storeArr = [...inputArr];
      // ...原有计算逻辑
    
      const result = storeArr[0];
      console.log("计算结果:", result);
      // 更新状态展示结果
      setStoreArr([result]);
      setActiveKey(result);
      return result;
    }
    

完整修复代码

import { useState } from 'react';

export default function App() {
  const [activeKey, setActiveKey] = useState(0);
  const [storeArr, setStoreArr] = useState([]);

  function click(selector) {
    setActiveKey(selector);
    if (selector !== "=") {
      setStoreArr(prev => [...prev, selector]);
    }
  }

  function clear() {
    setStoreArr([]);
    setActiveKey(0);
  }

  function calculate(inputArr) {
    if (!inputArr || inputArr.length === 0) return;
    // 复制数组,避免修改原状态
    const storeArr = [...inputArr];

    // 合并连续数字
    for (let i = 0; i < storeArr.length; i++) {
      if (
        typeof storeArr[i] === "number" &&
        typeof storeArr[i + 1] === "number"
      ) {
        storeArr[i] = storeArr[i] * 10 + storeArr[i + 1];
        storeArr.splice(i + 1, 1);
        i--;
      }
    }

    // 先处理乘除
    for (let i = 0; i < storeArr.length; i++) {
      if (storeArr[i] === "x") {
        storeArr[i - 1] = storeArr[i - 1] * storeArr[i + 1];
        storeArr.splice(i, 2);
        i--;
      } else if (storeArr[i] === "/") {
        storeArr[i - 1] = storeArr[i - 1] / storeArr[i + 1];
        storeArr.splice(i, 2);
        i--;
      }
    }

    // 再处理加减
    for (let i = 0; i < storeArr.length; i++) {
      if (storeArr[i] === "+") {
        storeArr[i - 1] = storeArr[i - 1] + storeArr[i + 1];
        storeArr.splice(i, 2);
        i--;
      } else if (storeArr[i] === "-") {
        storeArr[i - 1] = storeArr[i - 1] - storeArr[i + 1];
        storeArr.splice(i, 2);
        i--;
      }
    }

    const result = storeArr[0];
    console.log("计算结果:", result);
    // 更新状态展示结果
    setStoreArr([result]);
    setActiveKey(result);
    return result;
  }

  const topFuncs = [
    { name: "clear", text: "AC" },
    { name: "divide", text: "/" }
  ];

  const numsDiv = [
    { name: "seven", text: 7 },
    { name: "eight", text: 8 },
    { name: "nine", text: 9 },
    { name: "four", text: 4 },
    { name: "five", text: 5 },
    { name: "six", text: 6 },
    { name: "one", text: 1 },
    { name: "two", text: 2 },
    { name: "three", text: 3 },
    { name: "zero", text: 0 },
    { name: "decimal", text: "." }
  ];

  const rightDiv = [
    { name: "multiply", text: "x" },
    { name: "subtract", text: "-" },
    { name: "add", text: "+" },
    { name: "equals", text: "=" }
  ];

  return (
    <div className="App">
      <div id="outer-div" className="outer-div">
        <div className="store-display">{storeArr}</div>
        <div id="display" className="display">
          {activeKey}
        </div>

        <div className="left-right">
          <div id="left-div" className="left-div">
            <div className="top-funcs">
              {topFuncs.map((i) => (
                <button
                  id={i.name}
                  className="btn"
                  key={i.text}
                  onClick={() => {
                    if (i.text === "AC") {
                      return clear();
                    } else {
                      click(i.text);
                    }
                  }}
                >
                  {i.text}
                </button>
              ))}
            </div>
            <div id="nums-div">
              {numsDiv.map((i) => (
                <button
                  id={i.name}
                  className="btn"
                  key={i.text}
                  onClick={() => click(i.text)}
                >
                  {i.text}
                </button>
              ))}
            </div>
          </div>
          <div id="right-div" className="right-div">
            {rightDiv.map((i) => (
              <button
                id={i.name}
                className="btn"
                key={i.text}
                onClick={() => {
                  if (i.text === "=") {
                    calculate(storeArr);
                  } else {
                    click(i.text);
                  }
                }}
              >
                {i.text}
              </button>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 02:21:02