В этой статье основное внимание уделяется поведению immer.js в различных условиях. Обладая этими знаниями, вы будете знать, как можно оптимизировать производительность современного redux
при использовании createSlice
для редьюсеров записи (поскольку он использует immer.js за сценой для изменения состояний).
Разминка: ничего не меняйте
Когда вы ничего не изменяете с помощью функции produce
, она возвращает ЖЕ эталонный объект.
import produce from "immer"; const users = [ { id: 1, username: "Jerry" }, { id: 2, username: "Tom" } ]; const nextUsers = produce(users, (draft) => {}); console.log(nextUsers === users); // true
Изменение массива объектов
Когда вы изменяете поле объекта внутри массива с помощью функции produce
, происходят следующие эффекты:
- Создается новая ссылка на измененный вами объект.
- Вложенные объекты не затрагиваются. Он сохранит ту же ссылку.
- Будет создана новая ссылка на массив, содержащий этот объект.
- Однако, исходя из 3, элементы массива, которые не изменены, сохранят ту же ссылку.
import produce from “immer”; const users = [ { id: 1, username: “Jerry”, settings: { notification: true } }, { id: 2, username: “Tom”, settings: { notification: false } } ]; const nextUsers = produce(users, (draft) => { draft[1].username = “Tom Am”; }); console.log(nextUsers[1] === users[1]); // 1. false console.log(nextUsers[1].settings === users[1].settings); // 2. true console.log(nextUsers === users); // 3. false console.log(nextUsers[0] === users[0]); // 4. true
Немного изменим программу:
const users = [ { id: 1, username: “Jerry”, hobbies: ["music", "sports"] }, { id: 2, username: “Tom”, hobbies: ["drama", "arts"] }, ]; const nextUsers = produce(users, (draft) => { draft[1].hobbies[0] = "economics"; }); console.log(nextUsers[1] === users[1]); // 1. false console.log(nextUsers[1].hobbies === users[1].hobbies); // 2. false console.log(nextUsers === users); // 3. false console.log(nextUsers[0] === users[0]); // 4. true
Вышеприведенная программа изменена, чтобы изменить элемент массива объекта внутри массива. Это будет иметь следующий эффект:
- Создается новая ссылка на измененный вами объект.
- Создается новая ссылка измененного массива.
- Будет создана новая ссылка на массив, содержащий этот объект.
- Однако, исходя из 3, элементы массива, которые не изменены, сохранят ту же ссылку.
Используя приведенные выше знания, вы могли бы спроектировать хранилище redux
с эффективными редукторами, которые могли бы предотвратить ненужный повторный рендеринг!