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

React.js中使用setState时页面自动重载重置该如何解决?

问题原因

  • 你直接用原生innerHTML操作DOM修改格子内容,这部分修改没有同步到React的状态中。当你调用setState时,React会触发组件重新渲染,会按照return里的模板重新生成DOM结构,你手动修改的原生DOM内容自然就被重置了。
  • 你的棋盘格子状态没有存储在React状态里,组件重渲染时没有数据源可以保留之前的落子记录。
  • 目前的落子逻辑和状态更新是割裂的,玩家切换、回合数更新没有和落子行为绑定。

修复方案

1. 重构状态结构

把棋盘的落子数据也加入state,用长度为9的数组或者3x3的二维数组存储每个格子的内容,后续所有落子、玩家切换都通过修改state实现,完全不要手动操作DOM。

2. 调整落子和渲染逻辑

所有格子的内容从state中读取,点击格子时只修改state对应位置的数值,由React自动负责视图更新。

修正后的代码示例

<script type="text/babel">
    // 单独抽离格子组件
    function Column({ value, onClick }) {
      return <div className="column" onClick={onClick}>
        {value && <h1 className="symbols">{value}</h1>}
      </div>
    }
    // 抽离行组件,传入当前行的三个格子数据和点击回调
    function CreateRow({ rowData, onColumnClick }) {
      return <div className="row">
        {rowData.map((val, idx) => <Column key={idx} value={val} onClick={() => onColumnClick(idx)} />)}
      </div>
    }
    function Heading() {
      return <h1>井字棋</h1>
    }
    function TicTacToe() {
        const [state, setState] = React.useState({
          turn: 0,
          player: 'player1',
          // 3x3棋盘状态,初始为空
          board: Array(3).fill(null).map(() => Array(3).fill(null))
        });
        
        function columnClicked(rowIdx, colIdx) {
          // 已经落子的格子不能再改
          if (state.board[rowIdx][colIdx]) return
          const newBoard = state.board.map(row => [...row])
          newBoard[rowIdx][colIdx] = state.player === 'player1' ? 'X' : 'O'
          setState({
            ...state,
            board: newBoard,
            turn: state.turn + 1,
            player: state.player === 'player1' ? 'player2' : 'player1'
          })
        }

        return (
            <div>
                <Heading />
                <div className='container'>
                    {state.board.map((row, rowIdx) => 
                      <CreateRow 
                        key={rowIdx} 
                        rowData={row} 
                        onColumnClick={(colIdx) => columnClicked(rowIdx, colIdx)} 
                      />
                    )}
                </div>
                <p>当前玩家:{state.player === 'player1' ? 'X' : 'O'}</p>
            </div>
        );
    }

    ReactDOM.render(<TicTacToe />, document.getElementById('tic_tac_toe'));
</script>

核心改动说明

  • 移除了所有手动操作DOM的逻辑,所有视图内容都由state驱动渲染,调用setState后重渲染会保留所有落子记录,不会再重置。
  • 棋盘状态和玩家、回合数状态都统一管理,落子后自动切换玩家和更新回合数,不需要额外的切换按钮。
  • 组件拆分更合理,每个组件只负责对应部分的渲染和事件传递。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 20:15:02