Реакция setState не передает обновленные данные состояния в качестве реквизита для рендеринга компонента? - PullRequest
0 голосов
/ 25 июня 2019

Я новичок в React, пытаюсь создать приложение для карточных игр (использую реагирующее действие для функции перетаскивания).

Состояние board (в котором размещены карты) этого приложения - сетка 4x4, хранящаяся в виде двумерного массива

(начальные примеры усекаются)

this.state = {
      board: [
        [null, null, null, null],
        [null, null, null, null],
        [null, null, null, null],
        [null, null, null, null]
      ]
};

Когда карточки помещаются в пробел, вызывается эта функция setState (с использованием immutability-helper):

// 'bxy' is an object containing x & y position of board to find position
// 'player' is string of either 'p1' or 'p2' to figure out which player just played the card
// 'id' is unique integer of card to provide more card information
this.setState(
      {
        // add new card to board
        board: update(this.state.board, {
          [bxy.x]: { [bxy.y]: { $set: { id, player, x, y } } }
        })
      },
      // callback to run game logic based on newly placed card
      this.runAfterSetState(player, bxy, id)
    );

// Board would look something like this after first card placed:
// board: [
//   [null, null, null, null],
//   [null, {id: 3, player: "p1", x: 1, y: 1}, null, null],
//   [null, null, null, null],
//   [null, null, null, null]
// ]

То, что setState вызывает функцию обратного вызова runAfterSetState для запуска реальной игровой логической информации на основе только что сыгранной карты. Внутри этой функции есть еще один setState вызов. Это setState может произойти только в конкретном случае, когда, если имеется несколько карт противника, игрок должен нажать одну из этих карт противника. Я думаю, что для этого мне нужно было добавить новый ключ объекта к информации о вражеской карте в состоянии board (чтобы я мог затем добавлять стили, clickHandlers и т. Д.). Я думаю, что здесь все идет не так .

if (enemyCards > 1) {

      // new object key to add
      let objToAdd = { waitingToBeSelected: true };

      // update card object in board state with new object above
      enemyCards.map(card => {
        this.setState({
          board: update(this.state.board, {
            [card.x]: { [card.y]: { $merge: objToAdd } }
          })
        });
      });

      // this shows the correctly updated information
      console.log(this.state.board);
}

Несмотря на то, что приведенный выше журнал консоли, похоже, показывает, что информация обновлена ​​правильно, программа фактически не отражает это (используя инструмент React inspector Chrome). Я подозреваю, что моя программа повторно выполняет рендеринг компонента Board без этой недавно обновленной информации, по сути стирая ее? Насколько я могу судить, этот блок кода выше должен быть последним, который вызывается, и, следовательно, должен быть тем, что состояние компонента находится в конце.

Любая помощь здесь будет принята с благодарностью.


Codesandbox с полным рабочим кодом (и мои глупые комментарии):

https://codesandbox.io/s/billowing-leaf-81hw9?fontsize=14

Чтобы увидеть мою конкретную проблему, одна цветная карта должна иметь 2 или более стрелок, которые касаются соседних стрелок вражеских карт. Пример изображения: https://i.imgur.com/5SyrSBo.png (верхняя левая и левая стрелки красной карточки касаются стрелок синих карточек противника)

...