
Всем привет! Эта статья будет полезна тем, кто устал использовать constants в Redux (частично показано на превью выше). Под катом я покажу очередной возможный велосипед и как на нем кататься.

Модуль + документация (https://github.com/pavelivanov/redaction)
Введение
Использование Redux предполагает наличие экшнов (actions) и редьюсеров (reducers), а также констант (constants), которые используются для связи экшнов с редьюсерами посредством передачи type (типа экшна).
Пример использования:
const ADD_TODO = 'ADD_TODO' export { ADD_TODO }
import { ADD_TODO } from 'constants' export const addTODO = () => { return (dispatch) => { dispatch({ type: ADD_TODO, item }) } }
const ADD_TODO = 'ADD_TODO' const initialState = { TODO: [] } export default (state = initialState, action) => { switch (action.type) { case 'ADD_TODO': return { ...state, TODO: [ ...state.TODO, action.TODO ] } default: return state } }
В таком подходе немало минусов, начиная от использования констант, и заканчивая пробрасыванием dispatch метода во все компоненты, где нам необходимо вызвать экшн.
Простые Reducers
В Redaction я избавился от этих проблем. Все что вам нужно — это создать экшн и использовать его. Все.
Пример того же кода (выше) с использованием Redaction:
import { createAction } from 'redaction' export const initialState = { TODO: [] } export const addTODO = createAction((state, payload) => { return { ...state, TODO: [ ...state.TODO, payload ] } })
Принципиальное отличие: для передачи начального state делается экспорт из файла.
Request Actions
Что касается request экшнов, Redaction предлагает большое кол-во сахара. Пример использования:
С��здаем экшн:
// actions/users.js import { createAction } from 'redaction' export const getFeed = createAction({ endpoint: '/api/users/me/posts', method: 'GET' })
Вызываем созданный экшн:
// containers/Users/Feed.js import actions from 'core/actions' actions.users.getFeed({ subset: 'posts' })
В результате вызова getFeed в state будет:
{ users: { posts: { pending: false, data: RESPONSE_BODY, error: null } } }
Стоит заметить что createAction и метод, который он возвращает в результате выполнения принимают одинаковые параметры, т.е. subset можно было бы указать и в createAction, а потом еще его и переопределить при вызове в разных местах.
У каждого subset есть 3 состояния:
1) начало запроса { pending: true, data: null, error: null }
2) запрос выполнен { pending: false, data: RESPONSE_BODY, error: null }
3) запрос выполнен с ошибками { pending: false, data: null, error: RESPONSE_ERROR }
Больше не нужно мучаться с созданием трех экшенов с тремя разными типами для обработки нужного кейса из редьюсера.
Подробнее о createAction
Для отправки запросов внутри используется superagent. createAction в опциях принимает почти все параметры, которые используются в superagent.
Основные опции:
params <Object>
Любой ключ из опций может быть функцией, в этом случае одним из аргументов этой функции будет объект params. Исключениями являются onResponse и onError
endpoint <String | Function>
URL запроса.
Пример использования с params:
export const getFeed = createAction({ endpoint: ({ userId }) => `/api/users/${userId}/posts`, method: 'GET' }) getFeed({ params: { userId: 100 } })
subset <String | Function>
Название ключа, в котором будут храниться данные в state. Стоит учесть, что полный путь будет строиться по схеме: НАЗВАНИЕ_ФАЙЛА.subset
modifyResponse <Function>
Хендлер для редактирования ответа от сервера. Принимает два аргумента — объект Response от сервера и params. Ожидает возвращение нового объекта данных. При этом необходимо возвращать response.body
modifyState <Function>
Хендлер для изменения непосредственно state. Принимает два аргумента — весь объект State и params. Может быть полезно для изменения отдельных частей хранилища при использовании одного экшна. Использовать с осторожностью!
onResponse <Function>
Хендлер, вызывающийся при удачном выполнении запроса, принимает один аргумент — объект Response от сервера
onError <Function>
Хендлер, вызывающийся при невыполнении запроса, принимает два аргумента — объект ошибки и объект Response от сервера
Процесс инициализации Redaction
Я решил не писать на русском процесс инициализации, все это есть в документации на странице репозитория, НО, если будет достаточно желающих — я могу расширить статью, добавив такое описание.
Заключение
Буду рад, если мой модуль окажется полезен. Открыт для вопросов, замечаний и предложений по расширению функциональности. Исходный код модуля, доступен в GitHub репозитории
UPD1: переименовал модуль в RedAction (https://github.com/pavelivanov/redaction)
