Разве вас не беспокоил огромный объем работы, который вам придется проделать с проектом, если вы используете Redux в качестве инструмента управления состоянием?
Хотите использовать Relessjs немедленно? Перейдите на npmjs.com/package/relessjs
У меня есть! Особенно, когда проект растет. Затем я хочу оставить вещи СУХИМИ и поместить мои Типы действий в одно место, потому что мне нужно везде ссылаться на них. Да, я знаю, вы все еще можете вставить туда струны { type: “FILTER" }
, но тогда я должен сопоставить их с моими редюсерами, чтобы они были уже мокрыми (не СУХИМИ).
Это особенно раздражает, когда мне приходится создавать фабрики действий, чтобы делать некоторые асинхронные вещи. Вызов фабрики, обращение к типам действий, использование типов в созданных действиях и, не забывайте, сокращение их.
Реализация поиска в Redux
Допустим, у меня есть приложение ToDo, и я хочу, чтобы todo фильтровались на основе текста. Простая функция поиска. Чтобы реализовать это, мне пришлось бы сделать следующее:
- добавить тип действия
var actions = { filter: “FILTER” }
в todo-actions.js (здесь я поместил все свои константы, чтобы убедиться, что он остается СУХИМ) - импортировать todo-actions.js в todo-reducers.js
- создать новое дело для
actions.filter
вreducer
- импортировать todo-actions.js в search-component.js
- реализовать
dispatch({ type: actions.filter, payload: event.target.value })
, чтобы запустить цикл
Да, слишком… много… работы…Мы можем сделать лучше:
- удалить шаг 1 (нет необходимости в типе действия);
- удалить шаг 2 (без типов действий означает: без констант);
- удалить шаг 4 (там же); и
- вместо шага 5 (вызов
dispatch()
) мы просто вызовем редюсерreducers.search(payload)
и - реализовать шаг 3 в редукторе
Реализация поиска в Reless
Я строил Relessjs. Пакет, обеспечивающий те же основные концепции архитектуры Flux, что и Redux, но с меньшими затратами.
Итак, теперь мы просто вызываем Reducer из View и получаем новое State, в котором View будет перерисовано.
Relessjs: однонаправленный поток данных без накладных расходов
Теперь моя новая функция поиска в приложении ToDo упрощена до двух шагов:
- Создайте редьюсер с именем
search(payload)
в список редьюсеров из Reless. - Вызов
reducers.search(input.value)
из нового компонента поиска
Потрясающе правильно! Просто создайте и вызовите.
Простота: создайте редьюсер, вызовите редьюсер
Сила Релесса
Ниже приведены несколько примеров возможностей, которые может предложить Reless.
Установка значения, чтобы просто установить состояние, редюсер имеет следующий тип payload => state
: функция, которая получает payload
и возвращает новый частичный state
. Частичное состояние, потому что оно объединяется с существующим состоянием. Это устраняет необходимость в Object.assign({}, value)
или { ...state }
на корневом уровне.
Увеличение счетчика, обновление состояния на основе другого состояния:
Как показано выше (установка значения), вы не получаете состояние в качестве второго параметра в первой функции. Для использования состояния Reless позволяет вернуть функцию из редуктора типа state => state
. Таким образом, вы можете использовать state
, переданный во второй функции.
var store = new Reless({ state: { counter: 0 }, reducers: { increment: payload => state => ({ counter: state.counter + 1 }) } })
Извлечение данных, некоторые асинхронные действия (и использование частичного состояния):
Ну, теперь вы знаете упражнение. Вы можете вернуть другую функцию типа reducers => state
, где вы можете вызвать другую reducer
таким же образом, как указано выше, и/или вернуть state
, которая вступает в силу сразу после завершения функции.
var store = new Reless({ state: { todos: [] }, reducers: { getAllTodos: payload => state => reducers => { fetch('some.url/api/todos') .then((todos) => reducers.setTodos(todos)) return ({ loading: true }) }, // since Reless does a merge we can return // a partial state instead of a full state setTodos: todos => ({ todos }) })
Обратный отсчет таймера, постоянное выполнение чего-либо в зависимости от последнего состояния:
Для этого нам нужно сделать небольшую хитрость. Вместо того, чтобы вызывать редюсер с payload
, мы вызываем его с другой функцией, которая возвращает полезную нагрузку state => payload
. Таким образом мы получаем доступ к последней версии state
.
(В приведенном ниже конкретном случае вы также можете просто вызвать decrement
, но в других случаях вы можете вызвать reducer
(setCounter
) с полезной нагрузкой)
var store = new Reless({ state: { counter: 20 }, reducers: { decrement: () => state => ({ state.counter: state.counter-1 }), setCounter: payload => ({ counter: payload }), getAllTodos: payload => state => reducers => { var countdownHandle = setInterval(() => { if (state.counter) reducers.setCounter(state => state.counter - 1) else clearInterval(countdownHandle) }, 1000) } })
Не забудьте похлопать, если вам понравилось. Однако, если вы считаете, что что-то плохо сформулировано, пожалуйста, дайте мне обратную связь. Я ценю это.