重复键警告和 ui 行为异常

Duplicates keys warning and ui acts strange

作为快速学习的一部分,我正在尝试实现井字游戏,但遇到了 2 个奇怪的问题。我试图查看 CSS,它使用 Flexbox 并固定高度和宽度,我填满整行它又回到原来的形状。

  1. 尽管我给了它唯一的键,但我得到了重复的警告键。

  2. 当点击元素时,方块掉落!好奇怪。

谢谢,

import React, { useState } from 'react';
import './App.css';

const checkWinner = ({ board }) => {
}

const setXo = ({ board, setBoard, row, col, nextPlayer, setNextPlayer }) => {
  if (board[row][col] !== null)
    return alert('already in use')

  if (nextPlayer) {
    const newBoard = board
    newBoard[row][col] = 'O'
    setBoard(newBoard)
  } else {
    const newBoard = board
    newBoard[row][col] = 'X'
    setBoard(newBoard)
  }

  setNextPlayer(!nextPlayer)
}

const Row = props => {
  return (
    <button style={{ width: 100, height: 100 }} onClick={() => setXo(props)}>
      <h1>{props.board[props.row][props.col]}</h1>
    </button>
  )
}

const Column = props => props.board.map((value, index) => {
  console.log([props.row,index].join(''))
  return (
    <Row
      board={props.board}
      setBoard={props.setBoard}
      row={props.row}
      col={index}
      key={[props.row,index].join('')}
      nextPlayer={props.nextPlayer}
      setNextPlayer={props.setNextPlayer}
    />
  )
})


const Board = props => {
  console.log(props.board.length)
  return props.board.map((i, index) => {
    console.log(`index is: ${index}`)
    return (
      <div style={{ height: 100 }}>
        <Column
          key={index.toString()}
          row={index}
          style={{ marginTop: 20, border: 2, borderColor: 'black' }}
          board={props.board}
          setBoard={props.setBoard}
          nextPlayer={props.nextPlayer}
          setNextPlayer={props.setNextPlayer}
        />
      </div>)
  })
}

const App = () => {
  const INITIAL_BOARD = Array(3).fill(null).map(() => Array(3).fill(null));
  const [nextPlayer, setNextPlayer] = useState(false)
  const [board, setBoard] = useState(INITIAL_BOARD)
  const setPlayer = nextPlayer => nextPlayer ? 'Player 2' : 'Player 1'
  console.log(board)
  return (
    <div className="App">
      <h2>X/O Game</h2>
      <Board
        board={board}
        setBoard={setBoard}
        nextPlayer={nextPlayer}
        setNextPlayer={setNextPlayer}
      />
      <h2>The next player is: {setPlayer(nextPlayer)}</h2>
    </div>
  );
}
export default App;

这是 UI 问题:

关键部分我来回答一下

您现在的密码是:

const Board = props => {
  console.log(props.board.length)
  return props.board.map((i, index) => {
    console.log(`index is: ${index}`)
    return (
      <div style={{ height: 100 }}>
        <Column
          key={index.toString()}
          row={index}
          style={{ marginTop: 20, border: 2, borderColor: 'black' }}
          board={props.board}
          setBoard={props.setBoard}
          nextPlayer={props.nextPlayer}
          setNextPlayer={props.setNextPlayer}
        />
      </div>)
  })
}

如您所见,您正在为 Column 组件提供密钥。这是不正确的。正确的做法是给包装列的 div 标签一个键。

这样做的原因是密钥用于防止不必要的重新渲染。如果你把它放在 Column 中,你的 divs 仍然会被重新渲染,这不是你想要发生的。所以永远记住——当映射和返回一堆元素时,总是把 key 放在要返回的最上面的元素上。