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

React函数组件重渲染触发逻辑及游戏网格组件更新异常问题

问题:棋盘游戏状态更新后GameGrid组件不重渲染

场景说明

我正在开发一款棋盘游戏,流程是在PieceSelection组件选择棋子,再点击GameGrid中的格子完成落子。组件层级结构如下:

Game
  |- GameGrid
  |    |- Square
  |- PieceSelection

在Game组件中维护了两个状态:

  • currDisplay:存储GameGrid当前的棋盘显示内容
  • currSelectedPiece:记录当前选中的棋子

我给每个Square组件传递了点击回调函数,用于在格子被点击时通知Game组件对应的格子ID。Game组件中的落子处理函数如下:

// Inside Game component:

function handlePiecePlacement(squareID: number) {
        
    // 落子合法性校验...

    let newDisplay = currDisplay;
    newDisplay[squareID] = currSelectedPiece;
    setCurrDisplay(newDisplay);
}

这个函数通过props先传给GameGrid,再由GameGrid传递给每个Square组件。

遇到的问题

点击格子调用handlePiecePlacement后,虽然状态看似更新,但GameGrid组件并未重渲染,页面没有可见变化。但另一个处理选中棋子的函数handleClickToSelectPiece却能触发GameGrid重渲染,这两个函数都在Game组件中,为什么会有差异?

选中棋子的处理函数代码:

// Inside Game component:

function handleClickToSelectPiece(clicked: string) {
    setCurrSelectedPiece(clicked);
}

原因分析与解决方案

核心原因

React依赖状态的引用变化来触发组件重渲染:

  • 在handlePiecePlacement中,let newDisplay = currDisplay只是复制了原数组/对象的引用,修改newDisplay[squareID]本质是直接修改了原状态对象。之后调用setCurrDisplay传入的还是同一个引用,React会判定状态没有发生变化,因此不会触发GameGrid的重渲染。
  • 而handleClickToSelectPiece中,setCurrSelectedPiece传入的是新的字符串(值类型,每次赋值都会生成新的引用),React能检测到状态变化,进而触发依赖该状态的组件(包括GameGrid)重渲染。

修复代码

根据currDisplay的类型选择对应的副本创建方式:

  • 如果currDisplay是数组:
function handlePiecePlacement(squareID: number) {
    // 落子合法性校验...

    // 创建数组的浅副本
    let newDisplay = [...currDisplay];
    newDisplay[squareID] = currSelectedPiece;
    setCurrDisplay(newDisplay);
}
  • 如果currDisplay是对象:
function handlePiecePlacement(squareID: number) {
    // 落子合法性校验...

    // 创建对象的浅副本
    let newDisplay = {...currDisplay};
    newDisplay[squareID] = currSelectedPiece;
    setCurrDisplay(newDisplay);
}

不需要主动通知GameGrid重渲染,只要保证状态更新时传入新的引用,React会自动检测到GameGrid的display props变化,触发组件重渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 12:37:39