Предупреждение о дубликатах ключей и странный пользовательский интерфейс - PullRequest
0 голосов
/ 17 июня 2020

Часть быстрого обучения Я пытаюсь реализовать ti c ta c toe game и столкнулся с двумя странными проблемами. Я попытался увидеть 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

1 Ответ

0 голосов
/ 04 июля 2020

Я собираюсь ответить по поводу ключевой части.

Ваш код сейчас:

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 в самый верхний возвращаемый элемент.

...