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

React开发井字棋游戏时遇TypeError读取未定义属性错误

问题分析

点击方块后页面空白并报错,核心原因有两个:

  1. 状态更新破坏数组结构:App组件中square是数组类型,但Square组件调用setSquare时直接传入单个对象,替换了原本的数组。后续App尝试访问square[0]时会得到undefined,导致Square组件接收的square为undefined,访问square.value就触发报错。
  2. 初始数组元素引用重复:使用Array(9).fill({value: null, isClick: false})创建数组时,所有元素都是同一个对象的引用,后续修改任意一个元素会意外影响其他方块的状态。
修复后的完整代码
import React, { useState } from "react";

const App = () => {
  const [turn, setTurn] = useState(false);
  // 用Array.from创建独立对象的数组,避免引用重复
  const [square, setSquare] = useState(Array.from({length:9}, () => ({value: null, isClick: false})))

  return (
    <div>
      <h1>Turn: {turn ? "O" : "X"}</h1>
      <div className="board-row">
        {/* 给每个Square传递index,明确修改的是哪个位置的方块 */}
        <Square turn={turn} setTurn={setTurn} square={square[0]} setSquare={setSquare} index={0} />
        <Square turn={turn} setTurn={setTurn} square={square[1]} setSquare={setSquare} index={1} />
        <Square turn={turn} setTurn={setTurn} square={square[2]} setSquare={setSquare} index={2} />
      </div>
      <div className="board-row">
        <Square turn={turn} setTurn={setTurn} square={square[3]} setSquare={setSquare} index={3} />
        <Square turn={turn} setTurn={setTurn} square={square[4]} setSquare={setSquare} index={4} />
        <Square turn={turn} setTurn={setTurn} square={square[5]} setSquare={setSquare} index={5} />
      </div>
      <div className="board-row">
        <Square turn={turn} setTurn={setTurn} square={square[6]} setSquare={setSquare} index={6} />
        <Square turn={turn} setTurn={setTurn} square={square[7]} setSquare={setSquare} index={7} />
        <Square turn={turn} setTurn={setTurn} square={square[8]} setSquare={setSquare} index={8} />
      </div>
    </div>
  );
};

export default App;

const Square = ({ turn, setTurn, square, setSquare, index }) => {
    
  const clickHandle = () => {
    if (!square.isClick) {
      // 复制原数组,修改对应索引的元素,保持数组结构
      setSquare(prev => {
        const newSquare = [...prev];
        newSquare[index] = {value: turn ? "O" : "X", isClick: true};
        return newSquare;
      });
      setTurn(!turn);
    }
};

  return (
    <div>
      <button className="square" onClick={clickHandle}>
        {square.value}
      </button>
    </div>
  );
};
关键修复点
  • 传递索引标识位置:给每个Square组件添加index属性,明确当前方块在数组中的位置。
  • 正确更新数组状态:使用函数式更新setSquare(prev => ...),先复制原数组,再修改对应索引的元素,确保状态始终是数组类型。
  • 初始化独立元素数组:用Array.from替代fill,创建9个独立的对象,避免引用共享导致的意外状态变更。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 19:53:14