Почему Immer хорошо работает для неизменяемости состояния React?

В React использование неизменяемого состояния позволяет быстро и дешево сравнить дерево состояний до и после изменения. В результате каждый компонент решает, выполнять ли его повторную визуализацию перед выполнением каких-либо дорогостоящих операций DOM.

И я надеюсь, вы это уже знаете;

JavaScript изменчив, и мы должны реализовать неизменяемость самостоятельно.

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

К счастью, существуют специализированные библиотеки JavaScript, такие как Immer, которые предусматривают неизменяемость дерева состояний по дизайну.

Что такое иммер и как он работает

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

В Immer есть 3 основных состояния.

  1. Текущее состояние: данные о фактическом состоянии
  2. Состояние черновика: все изменения будут применены к этому состоянию.
  3. Следующее состояние: это состояние создается на основе мутаций в состоянии черновика.

Immer работает довольно хорошо с точки зрения производительности по сравнению с Shallow copy с использованием object.assign () или оператора Spread в JavaScript. Если вам интересно узнать больше о сравнении производительности, обратитесь к статье Immer vs Shallow copy vs Immutable Perf Test, чтобы понять тесты.

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

Поскольку у вас есть базовое понимание Immer, давайте посмотрим, почему Immer признан одним из лучших решений для обеспечения неизменяемости.

Почему Immer хорошо работает для неизменяемости состояния React?

У вас может возникнуть ощущение, что Immer усложняет ваш код, если вы работаете с простыми состояниями. Но Immer становится очень полезным, когда дело доходит до обработки более сложных данных.

Чтобы лучше понять это, давайте рассмотрим знаменитый пример редуктора React:

export default (state = {}, action) => {
    switch (action.type) {
        case GET_ITEMS:
            return {
                ...state,
                ...action.items.reduce((obj, item) => {
                    obj[item.id] = item
                    return obj
                }, {})
            }
        default:
            return state
    }
}

В приведенном выше коде показан типичный редуктор React-Redux, который использует оператор распространения ES6 для погружения во вложенные уровни объекта дерева состояний для обновления значений. Мы можем легко уменьшить сложность приведенного выше кода с помощью Immer.

Давайте рассмотрим пример того, как мы можем использовать Immer для уменьшения сложности на практике.

import produce from "immer"

export default produce((draft, action) => {
    switch (action.type) {
        case GET_ITEMS:
            action.items.forEach(item => {
                draft[item.id] = item
            })
    }
}, {})

В этом примере Immer упрощает код, используемый для распространения состояния. Вы также можете увидеть, что он изменяет объект с помощью цикла ForEach вместо функции ES6 reduce.

Давайте посмотрим на другой пример, где мы могли бы использовать Immer с React.

import produce from "immer";
this.state={
    id: 14,
    email: "stewie@familyguy.com",
    profile: {
      name: "Stewie Griffin",
      bio: "You know, the... the novel you've been working on",
      age:1
    }
}
changeBioAge = () => {
    this.setState(prevState => ({
        profile: {
            ...prevState.profile,
            age: prevState.profile.age + 1
        }
    }))
}

Этот код можно отредактировать, изменив состояние, как показано ниже.

changeBioAge = () => {
    this.setState(
        produce(draft => {
            draft.profile.age += 1
        })
    )
}

Как видите, Immer значительно сократил количество строк кода и его сложность.

Совет: создавайте лучшие библиотеки компонентов и системы проектирования

Делитесь компонентами между командами и проектами, чтобы ускорить разработку и убедиться, что ваши пользователи видят единообразный дизайн в каждой точке взаимодействия.

Инструменты OSS, такие как Bit, предлагают отличный опыт разработки для создания, совместного использования и внедрения компонентов в разных командах и приложениях. Создайте центр компонентов бесплатно попробуйте →

Можем ли мы использовать его с крючками?

Еще одна важная особенность Immer - его способность работать с React Hooks. Immer использует дополнительную библиотеку под названием use-immer для достижения этой функциональности. Давайте рассмотрим пример, чтобы лучше понять.

const [state, setState] = useState({
    id: 14,
    email: "stewie@familyguy.com",
    profile: {
      name: "Stewie Griffin",
      bio: "You know, the... the novel you've been working on",
      age:1
    }
  });
function changeBio(newBio) {
    setState(current => ({
      ...current,
      profile: {
        ...current.profile,
        bio: newBio
      }
    }));
  }

Мы можем еще больше упростить пример хуков, заменив useState на useImmer Hook. И мы также можем обновить компонент React, изменив состояние компонента.

import { useImmer } from 'use-immer';
const [state, setState] = useImmer({
    id: 14,
    email: "stewie@familyguy.com",
    profile: {
      name: "Stewie Griffin",
      bio: "You know, the... the novel you've been working on",
      age:1
    }
 });
function changeBio(newBio) {
   setState(draft => {
      draft.profile.bio = newBio;
    });
  }

Кроме того, мы можем использовать Immer для преобразования массивов и наборов в неизменяемые объекты. Карты, Наборы, созданные с помощью Immer, будут вызывать ошибки при изменении, позволяя разработчикам осознавать ошибку мутации.

Самое главное, Immer не ограничен React. Вы также можете легко использовать Immer с простым JavaScript.

Помимо иммутации, Immer помогает поддерживать хорошо написанную, читаемую кодовую базу, уменьшая ее сложность.

Последние мысли

Основываясь на моем опыте работы с Immer, я считаю, что это отличный вариант для использования с React. Это упростит ваш код и поможет управлять неизменяемостью по дизайну.

Вы можете найти больше информации об Immer, обратившись к их документации.

Спасибо за чтение !!!

Учить больше