Написание редукторов response-redux иногда может быть болезненным. В частности, вам, возможно, придется написать много шаблонного кода только для того, чтобы изменить одно значение или флаг во вложенном объекте. Мы увидим, как небольшой трюк может помочь нам уменьшить этот код.

TL; DR: вы можете использовать lodash / fp / set для неизменного изменения глубокого атрибута в вашем магазине. например, с import set from 'lodash/fp/set', а затем используйте set(path,value, state), например, с set(`manufacturers.${manufacturer}.models.${model}.options.colors.${color}`, true)(state)

Текущая ситуация

Когда вы пишете редукторы response-redux, вы должны быть осторожны, чтобы не изменять объекты в хранилище. Это не на 100% верно в приложении с простым реагированием, но поскольку вы, вероятно, используете какое-то поверхностное сравнение свойств где-то в своих приложениях, это правда. Это тот случай, если вы используете какой-то тип PureComponent, или используете react-redux для соединения с функциями mapStateToProps или любыми другими способ, которым вы могли бы использовать повторно выбрать, подключенный к вашему магазину. Если нет, вероятно, стоит.

Некоторые люди любят использовать объект Immutable.js в своем магазине. Если это ваш случай, и вы довольны этим, то вам действительно не нужно углубляться в статью. Лично я предпочитаю иметь дело с обычным JS-объектом в моем магазине. Я действительно обнаружил, что преобразование между объектом плана JS и Immutable является громоздким.

Итак, чтобы написать свои редукторы, чтобы они не мутировали объект в магазине, и используя обычный объект JS, вот как я писал свои редукторы.

Вероятно, вы можете найти другие способы написать это так, как вам больше нравится, или даже заявить, что форма моего хранилища redux может быть изменена, чтобы лучше соответствовать этой операции, но все же есть время, когда вы необходимо изменить глубокий атрибут в вашем магазине.

Думаю, теперь вы понимаете, почему я хотел найти лучшее решение. Я представлю один, но если у вас есть другие варианты, буду рад увидеть его в комментариях;)

Поиск решения

Теперь, когда наша проблема сформулирована правильно, вы, как хороший ленивый программист, наверное, задаетесь вопросом, есть ли решение этой конкретной потребности. Насколько я знаю, его нет. Опять же, не стесняйтесь поправлять меня или создавать свои на основе этой статьи. Собственно, последний раздел тоже должен быть вам интересен в этом случае.

Короче говоря, я искал решение этой проблемы, и, поскольку люди, с которыми я работаю, ужасные поклонники l odash, я подумал, что здесь есть решение. Я уже знал метод set, который полезен для установки значений атрибутов во вложенных объектах. Проблема с обычной версией метода set заключается в том, что он изменяет объект, для которого мы устанавливаем атрибут. Как мы уже говорили во введении, это не то, что нам здесь нужно. В основном то, что я искал, было неизменной версией set.

Я рад, что был не единственным.

Как вы можете видеть на скриншоте выше, мой герой Rico Sta. Круз задал этот вопрос в качестве lodash проблемы два года назад. Джон-Дэвид Далтон немедленно ответил, что он появится в l odash / fp, а Кайл Келли подтвердил это недавно, даже дав синтаксис, который мы могли бы использовать для настройки состояния стиля Redux

После этого я хотел проверить, использовалось ли это решение и рекомендовалось ли оно в сообществе React. Я сделал очень быструю проверку, но не нашел много ссылок на нее. Тем не менее, я нашел один пример, написанный ныне известным Дэном Абрамовым в этой статье о stackoverflow.

Я думаю, что теперь у нас есть ответ: вы можете использовать функцию lodash / fp / set в качестве помощника в редукторе react-redux, чтобы избежать бесполезного кода. Это даже делает кто-то из сообщества, чей талант признан жребием.

Идти дальше ?

Я не буду подробно рассказывать здесь, как вы можете использовать set для изменения объекта внутри массива. Фактически, это уже сделано в предыдущем примере. Если вы хотите изменить несколько свойств одновременно, я считаю, что вы также можете использовать для этого lodash / fp / merge или lodash / fp / defaultsDeep.

Кроме того, я уже говорил вам ранее, что lodash / fp / set может изменять объект неизменным способом. Это тот случай. Вы также хотите быть уверены в том, что он будет копировать только необходимые объекты, но сохранит ссылки на объекты, которые не затронуты. Это также верно: вы в безопасности, использование lodash / fp / set не приведет к бесполезному рендерингу.

Еще одна тема, которую здесь полезно выделить, - это производительность. В целом lodash работает отлично. Тем не менее, если это действительно важно для вас, я считаю, что здесь есть способ быть быстрее, чем lodash. Неизменяемость вокруг lodash / fp выполняется как слой вокруг начальной реализации методов lodash, здесь набор lodash. Это приводит к обходу объекта выполняется более одного раза: сложность выполнения больше, чем должна быть. Собственно, я создал минималистичную реализацию такой неизменяемой функции набора, которая будет работать только с одной итерацией.

Я сравнил эту реализацию с lodash / fp / set, и, несмотря на то, что он очень наивен, кажется, что он превосходит его, если я верю этому тесту jsPerf.

Это заставляет меня думать, что есть место для создания библиотеки, посвященной этому варианту использования и многому другому. Ближайшее, что я нашел до сих пор, - это reduceless, который является скорее оберткой вокруг магазина, поэтому вам не нужно писать редуктор, но по разным причинам я бы не рекомендовал его.