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

React中如何向组件函数传入正确的计数器值?

React循环生成Square组件时点击事件传参错误的修复

问题根源

你的代码存在两个关键问题:

  1. 变量作用域问题:用var声明循环变量i、j和计数器counter,var是函数级作用域,所有循环迭代的闭包共享同一个变量引用。当点击事件触发时,循环已经结束,变量值都变成了循环的最终结果(i=3,counter=9)。
  2. 传参错误:你给handleClick传递的参数是行号i,而不是每个Square对应的正确索引counter,这直接导致点击后拿到错误的位置值。

修复方案

方案1:改用let声明变量并修正传参

将var替换为let(块级作用域),同时确保传递正确的索引值:

export default function Board() {
  const [squares, setSquares] = useState(Array(9).fill(null));

  function handleClick(i) {
    const nextSquares = squares.slice();
    nextSquares[i] = "X";
    setSquares(nextSquares);
  }

  const boardRows = [];
  let counter = 0;

  for (let i = 0; i < 3; i++) {
    const boardSquares = [];
    for (let j = 0; j < 3; j++) {
      // 保存当前迭代的索引,避免闭包捕获变量引用
      const currentIndex = counter;
      boardSquares.push(
        <Square 
          value={squares[currentIndex]} 
          onSquareClick={() => handleClick(currentIndex)} 
        />
      );
      counter++;
    }
    boardRows.push(<div className="board-row">{boardSquares}</div>);
  }

  return boardRows;
}

方案2:用数组生成式简化代码(更推荐)

避免手动维护计数器,直接通过行号和列号计算索引,代码更简洁且不易出错:

export default function Board() {
  const [squares, setSquares] = useState(Array(9).fill(null));

  function handleClick(i) {
    const nextSquares = squares.slice();
    nextSquares[i] = "X";
    setSquares(nextSquares);
  }

  return Array.from({ length: 3 }, (_, rowIndex) => (
    <div className="board-row" key={rowIndex}>
      {Array.from({ length: 3 }, (_, colIndex) => {
        const index = rowIndex * 3 + colIndex;
        return (
          <Square 
            key={index}
            value={squares[index]} 
            onSquareClick={() => handleClick(index)} 
          />
        );
      })}
    </div>
  ));
}

关键说明

  • let声明的变量具有块级作用域,每次循环迭代都会创建新的变量实例,闭包会捕获当前迭代的变量值,而不是最终的引用。
  • 通过行号rowIndex和列号colIndex计算索引(rowIndex*3 + colIndex),可以精准获取每个Square对应的数组位置,无需手动维护计数器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 07:30:14