Мои последние два поста были на Утки высшего порядка. Мы построили один, затем отрефакторили его с помощью помощника createReducer.

Как и было обещано в последнем, время Рамды. Если вы найдете лучший способ реализовать что-то, пожалуйста, дайте мне знать! ❤️

Что это?

Официальный сайт

Ramda - это библиотека, которая упрощает функциональное программирование на JavaScript. Многие из наших рукописных шаблонов Redux легко выражаются в одной или двух функциях Ramda.

Я намеренно злоупотреблю Рамдой, чтобы продемонстрировать ее силу. Я не обязательно буду делать все в этом посте, но научиться понимать эти закономерности никогда не помешает.

Покажи мне код

Если вы читали предыдущую статью, вы помните, как мы реорганизовали редюсер так:

Хотя я намного больше доволен кодом после того, как пропустил его createReducer, Ramda предоставит дополнительную поддержку. Давайте начнем с дела reset и спустимся вниз.

actionTypes.reset

() => initialState

Все, что делает reset, - это возвращает исходное состояние. Чем может помочь Рамда?

R.always(initialState)

Берем initialState и запихиваем в R.always.

Из Документов Ramda:

Возвращает функцию, которая всегда возвращает заданное значение.

Вместо стрелочной функции у нас есть красивая R.always функция. Это может быть излишним, но я намеренно преувеличиваю, чтобы продемонстрировать часть арсенала Рамды.

actionTypes.addOne

(state, { item }) => [...state, item]

Объединить state (список) с заданным item.

(state, { item }) => R.append(item, state)
// or
(state, { item }) => R.concat(state, [item])

R.append документы:

Возвращает новый список, содержащий содержимое данного списка, за которым следует данный элемент.

R.concat документы:

Возвращает результат объединения заданных списков или строк.

Используйте R.append, чтобы создать новый список с item в конце, или превратите item в массив и объедините его в state с R.concat.

actionTypes.addMany

(state, { items }) => [...state, ...items]

На этот раз items уже является списком, и мы хотим объединить его с state.

Мы уже знаем, что R.concat добивается цели.

(state, { items }) => R.concat(state, items)

Вот код на данный момент.

actionTypes.removeOne

(state, { oldItem }) => state.filter((item) => (
   !findItemById(oldItem.id)(item)
)),

Напомним, что мы определили findItemById как:

findItemById = (id) => (item) => item.id === id;

Если findItemById(id)(item) возвращает false, оставьте элемент, в противном случае удалите его. Подведем итоги:

Видеть? Мы передали foods редуктору, а removeOne - id: 1. findItemById вернул true для нашего mango, поэтому он был удален.

У этого есть много переводов в Рамде.

Вы можете заменить state.filter на R.filter:

Вместо логического оператора НЕ, !, мы можем использовать R.not.

Мы можем скрыть параметр item с помощью R.complement.

Теперь мы становимся дерзкими. R.complement передаст item findItemById(oldItem.id) и вернет противоположное тому, что возвращает. Если findItemById(1)(item) вернет true, R.complement вернет false.

Однако было бы неплохо вообще не отрицать findItemById. Вы когда-нибудь слышали о R.reject?

Вместо дополнения findItemById мы можем использовать дополнение filterR.reject!

Бум!

Это означает, что когда findItemById(id)(item) вернет true, R.reject исключит item вместо того, чтобы включать его, как filter. За нас проделана тяжелая работа, и наш код стал намного проще.

actionTypes.updateOne

У Рамды есть R.map. Начнем с этого.

Но это даже не окончательная форма updateOne: введение R.when.

Обобщая документацию, R.when принимает три параметра: predicate, whenTrueFn и ваш тестовый объект x.

Если predicate вернет true, вы вернетесь whenTrueFn(x).
В противном случае вы вернетесь только x.

Простой пример. Давайте увеличим число, только, если оно равно 1.

В случае updateOne мы использовали R.when для инкапсуляции нашей предыдущей троичной логики. Если findItemById(id)(item) найдет совпадение и вернет true, мы вернем newItem. В противном случае мы просто вернем полученный item.

actionTypes.set

[actionTypes.set]: (_, { items }) => items

Это так просто, у меня нет хороших идей. Так вот плохой.

[actionTypes.set]: R.pipe(
   R.nthArg(1),
   R.prop('items')
)

Как сказал бы мой старый босс: Лол.

Силой R.pipe мы возвращаем свойство items второго аргумента. Это все, что у меня есть для тебя ...

Если вам интересно, как работает свёртка / компоновка, смотрите мою статью об этом.

Пожалуйста, хлопайте в ладоши / комментируйте, если вам понравилось! До скорого!

Береги себя,
Язид Бзадоу