React井字棋教程挑战报错:handleClick is not a function
React井字棋游戏循环生成Square组件报错问题
跟着React官方教程实现井字棋游戏时,尝试用循环生成Square组件替代硬编码,编写CreateSquares组件后点击方块出现handleClick is not a function错误,代码及报错信息如下:
代码
import { useState } from "react"; function Square({ value, onSquareClick }) { return ( <button className="square" onClick={onSquareClick} >{value}</button> ); } function CreateSquares(squares, handleClick) { const data = []; for (let i = 0; i < 3; i++) { const rows = []; for (let j = 0; j < 3; j++) { rows.push( <Square value={squares[j]} onSquareClick={() => handleClick(j)} key={j} /> ); } data.push( <div className="board-row" key={i}>{rows}</div> ); } return data; } function Board({ xIsNext, squares, onPlay }) { let winner = calculateWinner(squares); function handleClick(index) { if (squares[index] || winner) { return; } const nextSquares = squares.slice(); nextSquares[index] = xIsNext ? 'X' : 'O'; onPlay(nextSquares); } let status = winner ? "Winner: " + winner : "Next Player: " + (xIsNext ? "X" : "O"); return ( <> <div className="status">{status}</div> <CreateSquares squares={squares} handleClick={handleClick} /> {/* <div className="board-row"> <Square value={squares[0]} onSquareClick={() => handleClick(0)} /> <Square value={squares[1]} onSquareClick={() => handleClick(1)} /> <Square value={squares[2]} onSquareClick={() => handleClick(2)} /> </div> <div className="board-row"> <Square value={squares[3]} onSquareClick={() => handleClick(3)} /> <Square value={squares[4]} onSquareClick={() => handleClick(4)} /> <Square value={squares[5]} onSquareClick={() => handleClick(5)} /> </div> <div className="board-row"> <Square value={squares[6]} onSquareClick={() => handleClick(6)} /> <Square value={squares[7]} onSquareClick={() => handleClick(7)} /> <Square value={squares[8]} onSquareClick={() => handleClick(8)} /> </div> */} </> ); } export default function Game() { const [history, setHistory] = useState([Array(9).fill(null)]); const [currentMove, setCurrentMove] = useState(0); const xIsNext = currentMove % 2 === 0; const currentSquares = history[currentMove]; function handlePlay(nextSquares) { const nextHistory = [...history.slice(0, currentMove + 1), nextSquares]; setHistory(nextHistory); setCurrentMove(nextHistory.length - 1); } function jumpTo(nextMove) { setCurrentMove(nextMove); } const moves = history.map((squares, move) => { let description = move > 0 ? 'Go to move #' + move : "Go to game start"; return ( <li key={move}> <button onClick={() => { jumpTo(move) }}>{description}</button> </li> ); }); return ( <div className="game"> <div className="game-board"> <Board xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} /> </div> <div className="game-info"> <ol>{moves}</ol> </div> </div> ); } 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] ]; let len = lines.length; for (let i = 0; i < len; i++) { const [a, b, c] = lines[i]; if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) { return squares[a]; } } return null; }
报错信息
handleClick is not a function TypeError: handleClick is not a function at onSquareClick (http://localhost:3000/main.9d076070d9e17e2c1932.hot-update.js:51:30) at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:10826:18) at Object.invokeGuardedCallbackDev (http://localhost:3000/static/js/bundle.js:10870:20) at invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:10927:35) at invokeGuardedCallbackAndCatchFirstError (http://localhost:3000/static/js/bundle.js:10941:29) at executeDispatch (http://localhost:3000/static/js/bundle.js:15085:7) at processDispatchQueueItemsInOrder (http://localhost:3000/static/js/bundle.js:15111:11) at processDispatchQueue (http://localhost:3000/static/js/bundle.js:15122:9) at dispatchEventsForPlugins (http://localhost:3000/static/js/bundle.js:15131:7) at http://localhost:3000/static/js/bundle.js:15291:16
问题原因及修复方案
1. 组件参数接收错误
React组件的参数是一个props对象,而非单独的参数列表。你的CreateSquares函数定义为function CreateSquares(squares, handleClick),但实际调用时传入的squares={squares} handleClick={handleClick}会被包裹在props对象里,导致squares参数实际是props对象,handleClick参数为undefined,触发点击时就会报错。
修改方式:将函数参数改为解构props对象:
function CreateSquares({ squares, handleClick }) { // ... 原有逻辑 }
2. 方块索引计算错误
当前循环中,每一行的方块都使用j作为索引(0-2),导致所有行都取squares数组的前3个元素,点击时也只会触发0-2的索引,不符合井字棋9个位置的逻辑。需要计算正确的索引:i*3 + j(i是行号,j是列号)。
修改后的CreateSquares组件完整代码:
function CreateSquares({ squares, handleClick }) { const data = []; for (let i = 0; i < 3; i++) { const rows = []; for (let j = 0; j < 3; j++) { const index = i * 3 + j; rows.push( <Square value={squares[index]} onSquareClick={() => handleClick(index)} key={index} /> ); } data.push( <div className="board-row" key={i}>{rows}</div> ); } return data; }
将上述两处修改后,点击方块就能正常触发handleClick函数,且每个方块对应正确的squares数组位置。
内容的提问来源于stack exchange,提问作者Dipin
相关产品推荐
相关产品推荐

