🚀 Часть 2: Продвинутые техники в Zustand — миддлвары и оптимизация
Привет, друзья!
👋 Продолжаем разбираться с
Zustand. В этой части рассмотрим,когда использовать shallow и подключать миддлвары.
🔹 Что такое `shallow` и как он помогает?
По умолчанию Zustand сравнивает значения, возвращаемые селектором, с помощью строгого сравнения (
===
). Если вы подписываетесь на сложный объект, это может приводить к ненужным ререндерам, так как объект создаётся заново при каждом изменении состояния.
shallow
решает эту проблему: он выполняет
поверхностное сравнение полей объектов или массивов.
Пример:
import { shallow } from 'zustand/shallow';
const { fieldA, fieldB } = useStore(
(state) => ({ fieldA: state.fieldA, fieldB: state.fieldB }),
shallow
);
Здесь:
- Компонент обновится только тогда, когда
`fieldA` или `fieldB` реально изменятся.
- Если другие поля состояния изменятся, ререндера не будет.
Когда использовать
shallow
?
1. Если вы подписываетесь на объект с несколькими свойствами.
2. Для уменьшения ререндеров при работе с массивами или объектами.
Пример оптимизации с массивами:
const items = useStore((state) => state.items, shallow);
Если изменится структура или порядок элементов в массиве, компонент обновится. Но если массив остаётся неизменным, даже при обновлении других частей состояния, ререндер не произойдёт.
Использование
shallow
в паре с селекторами — мощный инструмент для повышения производительности!
🔹 Расширение через миддлвары
Zustand поддерживает миддлвары, которые позволяют добавлять дополнительную функциональность.
Популярные миддлвары:
1.
devtools: подключение инструментов разработчика.
2.
persist: сохранение состояния в
localStorage
.
3.
immer: удобное управление неизменяемым состоянием.
Пример с devtools:
import create from 'zustand';
import { devtools } from 'zustand/middleware';
const useStore = create(
devtools((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}))
);
Использование persist:
import create from 'zustand';
import { persist } from 'zustand/middleware';
const useStore = create(
persist(
(set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}),
{
name: 'counter-storage',
}
)
);
Теперь данные сохраняются между сессиями.
🔹 Работа с асинхронными действиями
Zustand поддерживает асинхронные операции через
set
.
Пример загрузки данных:
const useStore = create((set) => ({
users: [],
fetchUsers: async () => {
const response = await fetch('https://api.example.com/users');
const data = await response.json();
set({ users: data });
},
}));
В компоненте:
function UserList() {
const { users, fetchUsers } = useStore();
useEffect(() => {
fetchUsers();
}, [fetchUsers]);
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
🔹 Организация состояния в сложных приложениях
Когда приложение становится больше, важно правильно организовать Zustand.
Рекомендации:
1.
Разделяйте store на модули
Используйте несколько независимых хранилищ для различных частей приложения (например, auth, UI, данные).
Пример:
const useAuthStore = create((set) => ({
isAuthenticated: false,
login: () => set({ isAuthenticated: true }),
}));
const useUIStore = create((set) => ({
theme: 'light',
toggleTheme: () =>
set((state) => ({ theme: state.theme === 'light' ? 'dark' : 'light' })),
}));
2.
Используйте context для передачи store
Для улучшения читабельности в больших приложениях.
🎯 Заключение
Zustand — это не только простой state-менеджер, но и мощный инструмент для сложных приложений. Используя селекторы, миддлвары и асинхронные действия, вы можете оптимизировать производительность и упростить работу с состоянием.
ReactJs Daily | #pro