Часть 2 из 5

В этой части мы собираемся начать писать логику игры и добавлять тесты, чтобы убедиться, что наша игра будет работать.

Обновление от 22 июля 2019 г .: зависимости проекта обновлены.

  • Вавилон 7.x
  • Реагировать 16.x
  • Redux 4.x
  • Webpack 4.x

Полный список обновлений можно найти в package.json.

Новые зависимости

Чтобы написать тесты для наших действий, редукторов и операций, нам нужно будет добавить шутку в качестве зависимости разработчика в наш проект. Jest хорош, потому что он содержит все, что нам нужно для написания, запуска и сбора информации для нашего кода.

Мы также будем использовать redux-thunk, чтобы позволить нам условно отправлять действия для нашей игры.

yarn add --dev jest redux-thunk

Обновите тестовый сценарий файла package.json с помощью команды jest cli, чтобы выполнить все тесты, найденные в нашем проекте. По умолчанию Jest ищет файлы, которые начинаются с «test, * .test или * .spec».

// package.json
scripts: {
  ...,
  ...,
  "test": "jest"
}
// rest of package.json

Структура игры

Крестики-нолики - довольно простая игра. Существует сетка, составленная из трех на три квадрата, где каждый игрок делает ход, отмечая «X» или «O» в каждом квадрате. Выигрывает тот игрок, который первым соберет три в ряд, столбец или диагональ. Поскольку игра настолько проста, нам нужно всего четыре состояния.

  • board - числовой массив 3x3; текущее состояние игрового поля.
  • gameover - логический; есть победитель или это ничья.
  • player - число; текущий игрок или нет (0).
  • winner - число; игрок, выигравший игру, или ничья (0).

Управление государством

Мы собираемся использовать шаблон re-ducks, чтобы организовать наши редукторы, типы и действия redux в уток. Есть много способов управления и организации ваших файлов redux, но мне нравится шаблон re-ducks, потому что он разбивает состояние на папки, которыми легко управлять и которые упрощают нам написание тестов.

Типичная «утка» будет содержать следующие файлы:

  • index.js - экспорт для нашей утки.
  • reducers.js - редукторы redux.
  • actions.js - действия, которые могут быть использованы нашими операциями.
  • operations.js - операции, которые можно выполнять на нашей утке. Операция может отправлять одно или несколько действий.
  • selectors.js - отображает сложное состояние или производное значение, присвоенное реквизитам (необязательно).
  • types.js - константы типа действия.
  • test.js - тесты для нашей утки.

Утки хранятся в папке: src/state/ducks/.

Игровая утка - Редукторы, действия и виды

Единственная утка для нашей игры будет «игровой» уткой. Он будет содержать четыре состояния, перечисленные в разделе «Структура игры».

Создайте папку game в папке src/state/ducks/ и добавьте в нее файлы, перечисленные в разделе «Управление состоянием».

Мы начнем с написания тестов для наших редукторов, типов и действий. Откройте файл test.js и добавьте в него этот код:

Если вы запустите yarn test сейчас, вы получите неудачные тесты с сообщениями, в которых говорится: «TypeError: reducer не является функцией» или «TypeError: action. * Не является функцией», поскольку мы еще не реализовали их.

Откройте файл reducers.js, actions.js и types.js и добавьте следующую реализацию:

Запустите yarn test еще раз, и вы увидите, что все они уже проходят.

Игровая утка - операции и селекторы

Шаблон re-ducks описывает операции как интерфейс нашей утки. Операции, представленные через нашу утку, можно использовать для обновления состояния нашей утки.

Некоторые из наших утиных операций просты и могут быть представлены одна за другой с их действием, но есть другие, которые немного сложнее и требуют некоторой логики, прежде чем они отправят действия для изменения состояния.

Сначала мы обновим наш test.js файл новым разделом для операций, прежде чем реализовывать их в файлах operations.js и utils/game.js.

ПРИМЕЧАНИЕ. Мы не используем селекторы, но их можно использовать для получения нашего состояния утки и получения из него нового состояния. Это должны быть чистые функции, такие как редукторы, которые не изменяют состояние нашей утки.

Мы можем просто использовать пустой экспорт в selectors.js файле в качестве заполнителя.

// ducks/game/selector.js
export {};

Дичь - утка обнаженная

Теперь, когда мы реализовали нашу утку, нам нужно открыть ее, чтобы компоненты могли использовать ее для визуализации своего состояния.

В файле index.js экспортируйте редукторы, операции, селекторы и типы:

Создайте еще один index.js файл в src/state/ducks/, чтобы сгруппировать всех отдельных уток (пока только game). Это редукторы, которые будут объединены в корневом редукторе хранилища redux.

// src/state/ducks/index.js
export { default as gameState } from './game';
// ...
// more exports from other ducks

Redux магазин

Чтобы использовать игровую утку с redux, нам нужно добавить ее редукторы в хранилище redux. Создайте store.js файл вsrc/state/ для настройки магазина.

Мы экспортируем функцию configureStore, которая настраивает хранилище, объединяя все наши утки в один корневой редуктор, добавляя промежуточное программное обеспечение преобразователя, чтобы мы могли отложить или условно отправить действия и применить любое начальное состояние перед созданием и возвратом хранилища.

Использование утки

Откройте файл src/index.js и обновите его, чтобы использовать созданное нами хранилище redux.

Мы используем response-redux Provider, чтобы предоставить наш store всем нашим компонентам.

Позже, если мы захотим сохранить наше состояние в локальном хранилище, мы можем использовать переменную initialState, чтобы загрузить его снова, если мы обновим или вернемся в игру после перехода.

В файле src/views/App.jsx обновите его, чтобы использовать нашу игровую утку.

Проверьте, работает ли наше приложение, запустив yarn start.

Продолжение следует…

Весь исходный код в этой части можно найти здесь: