
Такие вещи, как состояние Redux, легко превратиться во вложенный беспорядок. Если вы хотите сохранить неизменяемость, вам нужно либо использовать специализированную библиотеку, такую как Immutable.JS, которая имеет собственный API для управления объектами, либо вы, по сути, сделаете следующее:
Это не только плохо выглядит (кто-нибудь код стрелки?), Но еще и очень плохо. Вы тратите так много времени на клонирование, и если вы облажаетесь, вы просто потеряете все преимущества неизменности.
ImmutableJS решает многие из этих проблем, но у него есть совершенно другой API для использования при манипулировании данными, и он не всегда интуитивно понятен (без разброса, без точечного синтаксиса, использует строки для доступа к вложенным объектам и т. Д.).
Вы также теряете много преимуществ в производительности, если конвертируете объект ImmutableJS в простой JS. Это означает, что вам либо нужно использовать ImmutableJS API в вашем коде React 😫, либо вам нужно добавить слой мемоизации с чем-то вроде повторного выбора, чтобы снизить влияние на производительность ».
Другое решение - нормализацию часто сложно реализовать, особенно если ваших источников данных нет. Преобразование между нормализованными и вложенными данными может стать кошмаром для непосвященных.
Решение
Несколько дней назад Мишель Вестстрат (создатель MobX) выпустил замечательную маленькую библиотеку под названием Immer (по-немецки Всегда). Он использует ES6 Proxies на объектах, созданных с его помощью, чтобы клонировать измененные разделы и вернуть этот клонированный объект в качестве ответа.
Это означает, что вы можете выполнять все свои стандартные операции мутации Javascript, а Immer сохранит неизменность под капотом.
Вот та же логика, что и выше, но на этот раз с использованием Immer:
Никогда не думал, что буду так счастлив что-то видоизменить в Javascript 😄! Но, несмотря на то, что вы некоторое время занимаетесь функциональным программированием, чувствуете себя немного грязным, эти мутации на самом деле создают неизменные изменения под капотом, вам просто не нужно беспокоиться обо всем клонировании.
У него 1600 звезд, и сейчас он рассчитывается на GitHub, и я думаю, что это многообещающий подход. Я настоятельно рекомендую ознакомиться с первым сообщением в блоге Мишеля Вестстрата об этом.
Как я его использую
Одна небольшая проблема, не отмеченная в документации Immer, заключается в том, что мутация означает, что мы больше не возвращаемся из каждого случая в наших операторах switch. Это означает, что мы должны использовать break..., что обычно не считается умным ходом 😕.
Break - это то, что у нас есть сегодня, самое близкое к старому goto методу программирования на ассемблере, и есть причина, по которой мы не раскрываем его в современных языках.
Goto Однако, если не считать отношений, это просто невероятно легко забыть. Фактически, несмотря на то, что я знал об этом, я полностью забыл вставить его, когда впервые тестировал Immer, что привело к нескольким очень запутанным минутам, пока я пытался выяснить, почему ничего не работает (как мои действия по созданию, так и по удалению были работает каждый раз, так что никогда ничего не менялось).
Вместо этого я решил использовать подход, аналогичный тому, который описан в разделе сокращение шаблонов документации Redux, а также подробно описан в этой статье.
Поскольку я не люблю переписывать шаблон, я создал следующую функцию:
Это делает предположение, что ваши действия похожи на этот стандарт по типу и полезной нагрузке.
Затем вы можете использовать его следующим образом:
(Простой пример CodeSandbox здесь)
Что намного лучше, чем стандартный метод клонирования распространения:
ImmutableJS не так уж и плох со стороны шаблонов, но использование в нем строк для слияния глубоких изменений немного пугает, поскольку ваши проверки времени компиляции не смогут помочь вам обнаружить ошибки.
Текущие ограничения
Я большой поклонник, но сейчас у библиотеки есть некоторые ограничения
- Прокси еще нет в Internet Explorer или Android React-Native, поэтому Immer возвращается к гораздо менее производительной версии es5 😕
- Immer сейчас поддерживает только объекты и массивы Javascript. В любом случае это 99% того, что я делаю в редукторах, но вам придется делать собственное клонирование, если вам нужны карты, примитивы или что-то особенное.
- Если вы решите не использовать switch (как у меня), вы потеряете приятный синтаксис провала, который предоставляют операторы switch.
- Если вы привыкли использовать только неизменяемые функции (срез вместо сращивания и т. Д.), Вам придется освежить свои знания об их изменяемых аналогах.
Заключение
Когда я пытаюсь научить другого разработчика, как использовать Redux, концепции неизменяемости и шаблона всегда блокируют. Я думаю, что Immer наконец-то может уменьшить эту когнитивную перегрузку при первом обучении, и я очень рад ее потенциалу.
Как всегда, не стесняйтесь комментировать ниже или писать мне в Твиттере @Tetheta. Сообщите мне, было ли это полезно для вас и что вы думаете о неизменности через изменчивость Иммера.
Написано с помощью StackEdit.