Самый простой пример 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 soshace.com