React Hooks не изменяет состояние объекта, пока я не прокручу страницу - PullRequest
0 голосов
/ 09 мая 2020

Я новичок в React, и у меня возникла проблема с рендерингом компонента ("setBoard" не вступит в силу, пока я не прокручу страницу):

function GameManager() {
  const [board, setBoard] = useState(new Board)

const handleKeyDown = useCallback(event => {
if (board.hasWon()) {
  return;
}
if (event.keyCode >= 37 && event.keyCode <= 40) {
  event.preventDefault();
  var direction = event.keyCode - 37;
  setBoard(board.move(direction))
}
  }, [])

useEffect(() => {
  window.addEventListener('keydown', handleKeyDown)
  return() => {window.removeEventListener('keydown', handleKeyDown)}

}, [handleKeyDown])
return (
  // <div onTouchStart={this.handleTouchStart.bind(this)} onTouchEnd={this.handleTouchEnd.bind(this)}>
  <div>
            <div class="heading" >
        <button class="restart-button" onClick={restartGame} onTouchEnd={restartGame}>New Game</button>
        < Score score={board.score} />
            </div>
        <BoardView board={board} />
      </div>
    );
}

Мой компонент не был повторно рендеринг, но значения объекта «доска» менялись:

return( </div>    <BoardView board={board} /> </div>)

После некоторого исследования я обнаружил, что React сравнивает, изменился ли объект с Object.is, и ответ верен, возможно, потому что как Я закодировал «доску»:

  Board.prototype.move = function (direction) {
    // 0 -> left, 1 -> up, 2 -> right, 3 -> down
    this.clearOldTiles();
    for (var i = 0; i < direction; ++i) {
      this.cells = rotateLeft(this.cells);
    }
    var hasChanged = this.moveLeft();
    for (var i = direction; i < 4; ++i) {
      this.cells = rotateLeft(this.cells);
    }
    if (hasChanged) {
      this.addRandomTile();
    }
    this.setPositions();
    return this;
  };

Может мне стоит вернуть что-то отличное от «вернуть это» в .move () ??

Есть идеи ??? (:

Спасибо за чтение!

EDIT:

Сейчас работает, но я не уверен, что это лучший подход:

Изменено свойства в компоненте вместо всего объекта:

<BoardView boardTiles={board.tiles} boardCells={board.cells} />

Теперь он должен обновляться при изменении board.tiles или board.cells.

Также измените способ установки объекта состояние (переменные отдельно)

board.move(direction)
      setBoard(prevBoard => ({...prevBoard, tiles: board.tiles, cells: board.cells, score: board.score}))

Эффективен ли этот способ? Можно ли оптимизировать?

Спасибо!

...