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> ); }
关键说明
- 状态提升:把原本Square自己的
value和mutate状态移到Board组件,这样所有格子的状态都在父组件统一管理,后续做胜负判断、重置游戏等逻辑都更方便。 - 回调传值:父组件定义
handleSquareClick函数,传递给每个Square;Square点击时调用这个函数,把自己的索引位置传回去,父组件就可以更新对应格子的值。 - 不可变更新:更新
squares数组时,用[...squares]复制原数组再修改,不要直接修改原数组,这是React状态更新的最佳实践,能保证组件正确重新渲染。
内容的提问来源于stack exchange,提问作者Emre YAZICI
相关产品推荐
相关产品推荐

