Middleware (Усилители). Логгер

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


Представляйте усилитель, как нечто стороннее, добавляющее функционал для нашего store.

Усилители — это middleware. Суть middleware функций — взять входные данные, добавить что-то и передать дальше.

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

Для лучшего понимания, предлагается написать бесполезный усилитель, выдающий console.log('ping') на каждое действие. При этом мы будем использовать предложенный redux метод добавления усилителей с помощью applyMiddleware.

Обновим файл конфигурации store:

store/configureStore.js

import { createStore, applyMiddleware } from 'redux'
import rootReducer from '../reducers'
import { ping } from './enhancers/ping' // <!-- подключаем наш enhancer

export default function configureStore(initialState) {
  const store = createStore(
    rootReducer,
    initialState,
    applyMiddleware(ping) // <!-- добавляем его в цепочку middleware'ов
  )

  if (module.hot) {
    module.hot.accept('../reducers', () => {
      const nextRootReducer = require('../reducers')
      store.replaceReducer(nextRootReducer)
    })
  }

  return store
}

Напишем усилитель:

store/enhancers/ping.js

/* eslint-disable */
export const ping = store => next => action => {
  console.log('ping')
  return next(action)
}
/* eslint-enable */

Похоже, что без ES5 версии здесь не обойтись:

var ping = function ping(store) {
  return function (next) {
    return function (action) {
      console.log('ping');
      return next(action);
    };
  };
};

Поехали:

  • eslint-disable — просто выключает проверку этого блока «линтером»;
  • ping — это функция, которая возвращает функцию; middleware — это всегда функция, которая обычно возвращает функцию, если только целью middleware не является прервать цепочку вызовов;
  • в возвращаемых функциях, благодаря applyMiddleware у нас становятся доступными аргументы, которые мы можем использовать во благо приложения:
    • store — redux-store нашего приложения;
    • next — функция-обертка, которая позволяет продолжить выполнение цепочки;
    • action — действие, которое было вызвано (как вы помните, вызванные действия — это store.dispatch)

Сейчас, при клике на кнопки, у нас в консоли появляется строка ping. Давайте изменим ее, написав простейший логгер: store/enhancers/ping.js

/* eslint-disable */
export const ping = store => next => action => {
  console.log(`Тип события: ${action.type}, дополнительные данные события: ${action.payload}`)
  return next(action)
}
/* eslint-enable */

Здесь использован новый строковый синтаксис. В прошлом наш console.log выглядел бы так:

console.log('Тип события: ' + action.type + ', дополнительные данные события: ' + action.payload)

Покликайте на кнопки, результат должен быть следующим: простой логгер скрин

Получившийся код.


Redux-logger

Отбросим наш велосипед и поставим популярный логгер.

npm i --save redux-logger

Удалите папку enchancers и измените configureStore.

src/store/configureStore.js

import { createStore, applyMiddleware } from 'redux'
import rootReducer from '../reducers'
import createLogger from 'redux-logger'


export default function configureStore(initialState) {
  const logger = createLogger()
  const store = createStore(
    rootReducer,
    initialState,
    applyMiddleware(logger)
  )

  if (module.hot) {
    module.hot.accept('../reducers', () => {
      const nextRootReducer = require('../reducers')
      store.replaceReducer(nextRootReducer)
    })
  }

  return store
}

Можете проверить — логгер достаточно информативный и удобный в использовании.

Таким образом, усилители — отличный способ добавить в наш процесс обработки действий некую прослойку с необходимой функциональностью.

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

Исходный код на текущий момент.

results matching ""

    No results matching ""