我正在按照this page中所示的井字游戏练习来学习react .在第Wrapping up章中,额外的作业(job)之一是:

重写Board以使用两个循环来制作正方形,而不是硬编码它们.

所以我从这个开始:

function Board({ xIsNext, squares, onPlay }) {
  function handleClick(i) {
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    const nextSquares = squares.slice();
    if (xIsNext) {
      nextSquares[i] = 'X';
    } else {
      nextSquares[i] = 'O';
    }
    onPlay(nextSquares);
  }

  const winner = calculateWinner(squares);
  let status;
  if (winner) {
    status = 'Winner: ' + winner;
  } else {
    status = 'Next player: ' + (xIsNext ? 'X' : 'O');
  }

  return (
    <>
      <div className="status">{status}</div>
      <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>
    </>
  );
}

对于这一点,请参阅更改注释以了解差异:

function Board({ xIsNext, squares, onPlay }) {

  function handleClick(i) {
    if (squares[i] || calculateWinner(squares)) {
      return;
    }
    const nextSquares = squares.slice();
    if (xIsNext) {
      nextSquares[i] = "X";
    }
    else {
      nextSquares[i] = "O";
    }
    onPlay(nextSquares);
  }

  const winner = calculateWinner(squares);
  let status;
  if (winner) {
    status = "Winner: " + winner;
  }
  else {
    status = "Next player: " + (xIsNext ? "X" : "O");
  }

  /* CHANGES START HERE */
  let content = [];
  let n=0;
  for (let i=0; i<3; i++) {
    let row = [];
    for (let j=0; j<3; j++) {
      row.push(<Square key={"square-" + n} value={squares[n]} onSquareClick={() => handleClick(n)} />);
      n++;
    }
    content.push(<div key={"row-" + i} className="board-row">{row}</div>);
  }

  return (
    <>
      <div className="status">{status}</div>
      {content}
    </>
  );
}

电路板被正确绘制,并且根据编译器的要求,数组中元素的键也被正确生成:

running buggy app

然而,如果我点击一个方块,单元格就不会像它应该的那样得到X/O标志,而且游戏跟踪器只记录第一步,而忽略随后对其他方块的任何点击.

clicked on top-left square

我可能会按照主要文件的建议使用.map(),但由于作业(job)中特别提到了two loops,我不知道我做错了什么.

我也查看了this answer,但我有多余的数据,我不知道放在哪里,比如类名称和键.

提前感谢您的帮助!

推荐答案

我认为问题与react 无关,只是您在循环之前声明了n变量,因此它始终具有最新的值(即9)

您的代码模拟(单击任意数字):

let n = 0
for (let i = 0; i < 3; i += 1) {
  for (let j = 0; j < 3; j += 1) {
    const el = document.createElement('div')
    el.textContent = n
    el.addEventListener('click', () => handleClick(n))
    document.body.appendChild(el)
    n += 1
  }
}

function handleClick(n) {
  console.log(n)
}

你应该根据ij来计算n

FIX:我的意思是,

for (let i = 0; i < 3; i += 1) {
  for (let j = 0; j < 3; j += 1) {
    const n = i * 3 + j
    const el = document.createElement('div')
    el.textContent = n
    el.addEventListener('click', () => handleClick(n))
    document.body.appendChild(el)
  }
}

function handleClick(n) {
  console.log(n)
}

Reactjs相关问答推荐

如何在Pivot模式下自定义标题?

为什么安装FLOBIT后,所有的输入FIELD现在都有一个蓝色的轮廓?

Npm运行构建`在Next.js 14中不起作用

安装后未渲染tailwind

如何使Reaction Select 选项菜单从选项数组的特定索引开始

如何访问子集合中的文档?

Google Firestore无法读取图像-react

阻止组件更新的多分派Redux Thunk或setState是否有任何问题

我在Route组件上使用元素属性,这样就不需要ID了吗?

.populate() 方法在 mongodb 中不起作用

如何使用服务器中的数据自动填充表单字段?

是否可以直接在 jsx 标签上使用 CSS 定义的 colored颜色 ?

如何在Next.js应用程序中为路由[slug]生成.html文件?

从 React 应用程序调用未经身份验证的 graphql 查询时出现错误:没有当前用户

为什么我会收到此错误:无法在我的react 包上读取 null 的属性(读取useState)?

在react 中从外部 api 渲染列表

如何在不重新加载页面的情况下加载新添加的数据?

加密 Django Rest Framework API 响应 + 解密响应应用程序中的响应

如何通过 Material Ui 设计将 Accordion 添加到您的 React 项目中?

Rtk 查询无效标签不使数据无效