React-Redux — Как создать простую игру про змейку, используя компоненты реакции, связанные с состоянием редукции.
Змея игра очень классическая игра. Змея ест пищу, чтобы вырасти, и умрет, если столкнется с самой собой.
Создание компонентов React
React — это библиотека для создания пользовательского интерфейса с концепцией компонентов. Компонент подобен одному объекту. Например, игра «Змейка» будет состоять из 3 основных компонентов; холст, змея и еда.
Учтите, что каждый компонент представляет собой комнату. В вашей canvas
комнате:
index.js
это дверь.
import Canvas from './canvas'; export default Canvas;
canvas.js
это мебель.
import Snake from '../snake/index'; import Food from '../food/index'; const Canvas = () => { return ( <div> <Snake /> <Food /> </div> ); }; export default Canvas;
style.css
насколько прекрасна твоя комната.
Комнаты snake
и food
находятся внутри canvas
комнаты. Но в структуре кода я разработал размещение их в каталоге одного уровня; components
. На всякий случай, если у нас может быть другой холст, на котором должна быть змея или еда, мы сможем использовать их повторно.
const Snake = () => { const renderSnake = () => { // a logic to render snake body base on location. ... } return rederSnake(); }; export default Snake;
Создание сервисов Redux
Redux — это библиотека для управления данными приложения. это поможет контролировать состояние данных. Когда данные изменяются, ваши реагирующие компоненты, использующие эти измененные данные, будут автоматически перерисовываться.
Во-первых, змея сможет двигаться по направлениям стрелок. Вы должны определить действия змеи, чтобы получить запрос на изменение направления. Запрос будет успешным, если он получит клавиши со стрелками, в противном случае это запрос с ошибкой.
- Вы должны определить
actionTypes
, чтобы сообщить змее, какие действия она может предпринять.
export const MOVE_REQUEST = 'MOVE_REQUEST'; export const MOVE_SUCCESS = 'MOVE_SUCCESS'; export const MOVE_FAILURE = 'MOVE_FAILURE';
- Затем вам нужно создать
actions
, чтобы змея смогла их забрать.
reducer
— это место для хранения и управления состоянием. В этом случае редьюсер обновит положение змеи, если змея переместится успешно.
worker
скорее поведение. Когда змея получит запрос на движение, она рассмотрит, является ли клавиша стрелкой или нет. Если ключом является клавиша со стрелкой, змея изменит направление следуя за клавишей. В противном случае змея продолжит движение в том же направлении.
index
предназначен для связывания действий и работника вместе. Чтобы змея знала, что когда это действие произойдет, какое поведение она должна предпринять.
import * as actionTypes from './actionTypes'; import * as worker from './worker'; export default function* watcherSaga() { yield takeLatest( actionTypes.MOVE_REQUEST, worker.watchMoveRequest, ); };
Применить Redux к приложению
Пока что мы уже знаем, как создавать реагирующие компоненты и редукционные сервисы. Следующее, как сообщить приложению о службах, которые мы только что создали.
На картинке выше вы увидите 3 новых файла; индекс, редукторы и саги.
reducers
иsagas
предназначены для объединения редьюсеров и саг в случае, если у нас есть более одного сервиса.
- Файл
index
похож на центр приложения, где вызываются реакции и редуксы, чтобы они могли работать вместе. Например,createStore
для сохранения состояния данных, применитеredux-logger
, чтобы приложение могло отображать журналы каждого действия, запускать саги и отображать компоненты.
Подключить React-Redux
Последний шаг — соединение реакции и редукции вместе. Помните, что у нас есть файл index.js
в качестве двери для каждого компонента реакции. Затем используйте connect from 'react-redux'
для ввода действий или состояния любых служб в компонент.
import { connect } from ‘react-redux’ import ComponentA from ‘./componentA’; import { actionA } from ‘../../services/aService/actions’; import { actionB } from ‘../../services/bService/actions’; const mapStateToProps = state => { return { dataA1: state.aServiceReducer.dataA1, dataA2: state.aServiceReducer.dataA2, dataB1: state.bServiceReducer.dataB1, }; }; const mapDispatchToProps = dispatch => { return { actionA: () => dispatch(actionA()), actionB: bParam => dispatch(actionB(bParam)), }; }; export default connect (mapStateToProps, mapDispatchToProps) (ComponentA);
Вернемся к игре со змеей. Компоненту змеи необходимо знать положение змеи, чтобы обновить ее положение на холсте.
import { connect } from 'react-redux'; import Snake from './snake'; const mapStateToProps = state => { return { snakePos: state.snakeServiceReducer.snakePos, } } export default connect(mapStateToProps, null)(Snake);
Поскольку нам нужно знать только данные о позиции, мы будем отображать только состояние(redux) в props(реагировать). Затем в snake.js
будут получены и переданы реквизиты snakePos
для рендеринга змеи.
const props = { snakePos: PropTypes.array.isRequired, }; const Snake = props => { const { snakePos } = props; const renderSnake = () => { // a logic to render snake body base on snakePos location. ... } return renderSnake(); }; Snake.propTypes = props; export default Snake;
Вывод
- создавать реактивные компоненты.
- создание избыточных сервисов включало три основных вещи; action, reducer и saga worker.
- [необязательно] в случае наличия нескольких редюсеров или саг. Используйте
combineReducers
, чтобы объединить несколько редукторов в один файл. И используйтеyield all
, чтобы объединить все рабочие саги. - создайте промежуточное ПО саги, чтобы применить саги к приложению.
- соедините redux с реагирующими компонентами, используя
connect from 'react-redux'
.
Весь исходный код вы можете найти здесь.