Самый простой пример side-effects это Logging. Далее мы с Вами создадим middleware который занимается Logging.
Создадим папку middlewares , а в ней файл logger.js:
export default store => next => action => {
console.log('---', 'before: ', store.getState())
console.log('---', 'dispatching', action)
next(action)
console.log('---', 'after', store.getState())middlewareэто функция которая принимает store, возвращает функцию которая принимает next, (функцию, чтобы передать управление дальше), которая в свою очередь возвращает функцию, которая принимает action, которая уже что-то делает. Такая запись дает возможность иметь доступ к текущему значению Вашегоstore , к next и action . Наш store будет показывать immutable.js структуры.(это происходит при помощи нашего recordsFromArray из reducer/utils.js) И что важно state нашего store может меняться на протяжении жизни этой middleware. Это мы увидим прямо здесь в нашем logger. Сначала мы сделаем dispatch того что у нас было видно состояние “до”, а далее вызовем next – это передача управления дальше. Обычно существуют целая цепочка middlewares, и они проходят одна за другой, т.е. мы обработали наш action в этой middleware и затем, мы передаем управление c помощью next в следующую, и когда middlewares заканчиваются она попадает в reducers, там обрабатывается и попадает в store. После того как мы закончим с dispatch этого action мы вернемся снова в наш middlewareи сможем получить актуальное состояние store после того как он обработался в reducers.
Теперь наш middleware нужно подключить в store. Заходим в store/index.jsи меняем его следующим образом:
import { createStore, applyMiddleware, compose } from 'redux'
import reducer from '../reducer'
import logger from '../middlewares/logger'
const enhancer = compose(
applyMiddleware(logger),
window.devToolsExtension ? window.devToolsExtension() : f => f
)
const store = createStore(reducer, {}, enhancer)
window.store = store
export default storeДля этого в store есть третий аргумент enhancer. Сперва подключаем наш middleware а также из redux нам понадобиться функция applyMiddleware которая может собрать все middlewares которые нам нужны. Пока подключаем только logger.
Теперь на каждый action у нас будет происходить Logging. Посмотрите на результаты работы нашего logger в console в браузере, к примеру, удалив одну из статей.
Конечно же middlewares создаются и сторонними разработчиками, вы можете их подключать – этим займемся чуть позже. Помимо middlewares существуют enhancersкоторые можно подключать без применения middleware. Хороший пример это redux devtools. Он позволяет посмотреть какие actions у Вас происходят, отменять action, восстановить его, увидеть какой state сейчас у вашего store. Рекомендуется поставить себе его в виде Chrome extension. В документации вы найдете информацию о том как подключить его к Вашему store. Если вы хотите подключить несколько middlewares вам нужно будет использовать функцию compose, которая также есть в redux . Пример подключения уже был нами написан в store/index.js. После перезагрузки приложения заработает наш redux devtools.
Так как middlewares вызываются все для каждого action, а нам зачастую это не нужно, то необходимо использовать здравый смысл и не создавать их сотнями, а также делать проверки на предмет надобности той или иной middleware. Еще важно помнить о порядке, они передаются по цепочке от первого к последнему и поэтому logger нужно ставить в конце, а скажем технические middlewares, например генерацию случайного id вам стоит ставить в начале.
Как упорядочить middlewares? В том порядке в котором вы их оглашаете, так они и сработают. Для примера добавим еще одну middleware которая просто будет передавать управление дальше, также вместе с action она передает ‘hello world’ или может передать случайный id (это может пригодиться для выполнения домашнего задания). После всех impot в store/index.js сразу добавим:
import { createStore, applyMiddleware, compose } from 'redux'
import reducer from '../reducer'
import logger from '../middlewares/logger'
const dumbMiddleware = store => next => action => next({...action, addition: 'hello world'})
const enhancer = compose(
applyMiddleware(dumbMiddleware, logger),
window.devToolsExtension ? window.devToolsExtension() : f => f
)
const store = createStore(reducer, {}, enhancer)
window.store = store
export default storeТакже в applyMiddleware она будет стоять первой, далее logger и redux devtools.
Домашнее задание: создать функционал добавления комментария к статье. Т.е. там где под каждой статьей есть комментарии, там должна появиться форма с кнопкой, которая добавляет комментарий к этой статье. Сохранять ее нигде не надо кроме Вашего store.
Код урока доступен у нас в репозитории.
We are looking forward to meeting you on our website blog.soshace.com


