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;

Вывод

  1. создавать реактивные компоненты.
  2. создание избыточных сервисов включало три основных вещи; action, reducer и saga worker.
  3. [необязательно] в случае наличия нескольких редюсеров или саг. Используйте combineReducers, чтобы объединить несколько редукторов в один файл. И используйте yield all, чтобы объединить все рабочие саги.
  4. создайте промежуточное ПО саги, чтобы применить саги к приложению.
  5. соедините redux с реагирующими компонентами, используя connect from 'react-redux'.

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