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

React井字棋状态更新异常:数组状态已更新但HTML未渲染

React井字棋状态更新后不重新渲染的问题解决

问题根源

你遇到的核心问题是直接原地修改了状态数组,React的状态更新依赖引用变化触发重渲染:

  • 在Box.js的handleClick里,const updatedArray = prevArr只是把原数组的引用赋值给新变量,修改updatedArray[props.index]本质是修改原状态数组,数组引用没发生变化。
  • React对数组/对象类型的状态做浅比较,发现引用没变就判定状态未更新,不会触发组件重渲染。
  • 另外Board.js里的isXTurn状态解构有误,多了个逗号,导致setIsXTurn没正确获取到状态更新函数,后续玩家切换会失效。

修复方案

  1. 修改数组状态时创建副本:更新arr状态时先复制原数组的副本,修改副本后再返回,确保引用变化。
  2. 修正状态解构错误:把const [isXTurn, ,setIsXTurn]改成const [isXTurn, setIsXTurn]。
  3. 点击后切换玩家:更新完arr状态后,调用setIsXTurn切换玩家回合。

修正后的完整代码

Board.js

import React from 'react'
import Box from './Box'
import './Board.css'

function Board() {
  // 初始化9格空棋盘
  const [arr, setArr] = React.useState(Array(9).fill(null))
  // 当前玩家是否为X(修正解构错误)
  const [isXTurn, setIsXTurn] = React.useState(true)
  // 整合props
  const props = { arr, setArr, isXTurn, setIsXTurn }
  
  // 生成Box元素列表
  const arrayEle = arr.map((ele, i) => (<Box {...props} value={ele} index={i} key={i}/>))

  return (
    <div className='board'>
      {arrayEle}
      {/* 用JSON.stringify展示数组状态,方便调试 */}
      {JSON.stringify(arr)}
    </div>
  );
}

export default Board;

Box.js

import React from 'react'
import './Box.css'

function Box(props) {
  // 根据值设置样式
  const style = props.value === 'X' ? 'box x' : 'box o'
  
  function handleClick(){
    // 已填充的格子不能点击
    if(props.value) return

    props.setArr(prevArr => {
      // 创建原数组的副本(关键:避免原地修改)
      const updatedArray = [...prevArr]
      updatedArray[props.index] = props.isXTurn ? 'X' : 'O'
      return updatedArray
    })
    // 切换玩家回合
    props.setIsXTurn(prev => !prev)
  }

  return (
    <button className={style} onClick={handleClick}>
      {props.value}
    </button>
  );
}

export default Box;

补充说明

  • 创建数组副本的方式不止扩展运算符,还可以用Array.from(prevArr)或者prevArr.slice(),核心都是不修改原状态数组。
  • 切换玩家时用setIsXTurn(prev => !prev)这种函数式更新更安全,避免依赖外部异步的isXTurn值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 20:35:28