Библиотека Immer решает проблему громоздкого синтаксиса, позволяя вам писать обычный, привычный «мутирующий» код. При этом сам оригинал объекта остается в полной безопасности, а на выходе получается чистая иммутабельная копия. Вся магия происходит благодаря встроенному в JavaScript механизму Proxy, который перехватывает ваши изменения.

🔍 Проблема: Глубокая вложенность БЕЗ Immer

Представьте, что у нас есть профиль пользователя, и нам нужно изменить значение darkTheme на true.

const user = {
  id: 1,
  info: {
    name: 'Алексей',
    settings: {
      theme: 'light',
      notifications: true
    }
  }
};

// Чтобы сохранить иммутабельность, нужно "развернуть" каждый уровень:
const updatedUser = {
  ...user,
  info: {
    ...user.info,
    settings: {
      ...user.info.settings,
      theme: 'dark' // Ради этой строчки пришлось писать всё выше
    }
  }
};

Минусы: Код тяжело читать, легко забыть написать ... на каком-то уровне и случайно потерять часть данных.

✨ Решение: Как эту задачу решает Immer

С Immer вы используете функцию produce. Она принимает два аргумента: исходный объект и функцию-мутатор. Внутри этой функции вы работаете с так называемым draft (черновиком) так, будто это обычный мутабельный объект.

import { produce } from 'immer';

const user = {
  id: 1,
  info: {
    name: 'Алексей',
    settings: {
      theme: 'light',
      notifications: true
    }
  }
};

// Просто меняем свойство напрямую в черновике!
const updatedUser = produce(user, (draft) => {
  draft.info.settings.theme = 'dark';
});

console.log(user.info.settings.theme);        // 'light' (Оригинал не изменился!)
console.log(updatedUser.info.settings.theme); // 'dark'  (Новый объект создан)

💎 Почему это круто?

  1. Никаких мутаций: Исходный объект user гарантированно защищен.
  2. Знакомый синтаксис: Вы можете использовать любые привычные методы, включая мутирующие методы массивов (push, pop, splice, shift).
  3. Умная память (Structural Sharing): Если в объекте user были другие ветки (например, draft.orders), которые вы не трогали, Immer не будет их копировать. Новый объект updatedUser просто сошлется на старые участки памяти для неизмененных данных.