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

React中如何实现子组件向父组件传递Props?(井字棋场景)

React井字棋:子组件向父组件传值实现方案

要实现Square组件把值传递给Board组件,核心用回调函数+状态提升的方式就行——React是单向数据流,子组件没法直接修改父组件的状态,得靠父组件传一个回调函数给子组件,子组件调用这个函数把数据传回去。而且井字棋里,把所有格子的状态统一放在父组件Board里管理,后续做胜负判断之类的逻辑会更方便。

改造父组件Board

把所有Square的状态统一存在Board的数组里,同时定义一个回调函数,让Square点击时调用这个函数更新状态:

import React, { useState } from "react";
import Square from "./Square";

export default function Board() {
  // 用数组存储9个格子的值,初始都是null
  const [squares, setSquares] = useState(Array(9).fill(null));
  // 记录当前下棋的玩家,X先下
  const [isXNext, setIsXNext] = useState(true);

  // 处理Square点击的回调函数,接收格子的索引位置
  function handleSquareClick(index) {
    // 如果已经有值或者已经分出胜负,直接返回(防止重复点击)
    if (squares[index] || calculateWinner(squares)) {
      return;
    }
    // 复制原数组,修改对应位置的值(不要直接修改原数组,遵循React不可变更新)
    const newSquares = [...squares];
    newSquares[index] = isXNext ? "X" : "O";
    setSquares(newSquares);
    // 切换玩家
    setIsXNext(!isXNext);
  }

  // 胜负判断函数(提前写好方便后续用)
  function calculateWinner(squares) {
    const lines = [
      [0, 1, 2],
      [3, 4, 5],
      [6, 7, 8],
      [0, 3, 6],
      [1, 4, 7],
      [2, 5, 8],
      [0, 4, 8],
      [2, 4, 6],
    ];
    for (let i = 0; i < lines.length; i++) {
      const [a, b, c] = lines[i];
      if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
        return squares[a];
      }
    }
    return null;
  }

  // 获取当前游戏状态文本
  const winner = calculateWinner(squares);
  let status;
  if (winner) {
    status = `胜利者: ${winner}`;
  } else {
    status = `下一个玩家: ${isXNext ? "X" : "O"}`;
  }

  return (
    <div className="game-board">
      <div className="status">{status}</div>
      {/* 给每个Square传递value、点击回调和索引 */}
      <Square value={squares[0]} onClick={() => handleSquareClick(0)} />
      <Square value={squares[1]} onClick={() => handleSquareClick(1)} />
      <Square value={squares[2]} onClick={() => handleSquareClick(2)} />
      <Square value={squares[3]} onClick={() => handleSquareClick(3)} />
      <Square value={squares[4]} onClick={() => handleSquareClick(4)} />
      <Square value={squares[5]} onClick={() => handleSquareClick(5)} />
      <Square value={squares[6]} onClick={() => handleSquareClick(6)} />
      <Square value={squares[7]} onClick={() => handleSquareClick(7)} />
      <Square value={squares[8]} onClick={() => handleSquareClick(8)} />
    </div>
  );
}

改造子组件Square

去掉自己的状态,直接用父组件传过来的value和onClick回调:

import React from "react";

export default function Square({ value, onClick }) {
  return (
    // 点击时调用父组件传过来的onClick函数
    <div className="square" onClick={onClick}>
      {value}
    </div>
  );
}

关键说明

  1. 状态提升:把原本Square自己的value和mutate状态移到Board组件,这样所有格子的状态都在父组件统一管理,后续做胜负判断、重置游戏等逻辑都更方便。
  2. 回调传值:父组件定义handleSquareClick函数,传递给每个Square;Square点击时调用这个函数,把自己的索引位置传回去,父组件就可以更新对应格子的值。
  3. 不可变更新:更新squares数组时,用[...squares]复制原数组再修改,不要直接修改原数组,这是React状态更新的最佳实践,能保证组件正确重新渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 21:18:33