Ідеальний стейт-менеджер для React у 2024 році
Незалежно від того, чи пишете ви великий продакш-застосунок десь в компанії, чи щось маленьке для власних потреб, вам потрібно використати якийсь менеджер стану в React. У вас теж так було? З коробки React не надає рішення, яке б задовольняло ці потреби. Звичайно, є Context, але він має свої проблеми.
На ринку є велика кількість розв’язань цієї проблеми, але універсальних та зручних — годі й шукати. Нещодавно я сам познайомився з новою бібліотекою, яка претендує на відкриття року у світі стейт-менеджменту для React. Називається вона Zustand. Назва трохи відлякує, напевно тому я так довго її уникав, але це німецьке слово «Zustand» вимовляється як «цуштанд» і означає «state» або «стан».
У відео на моєму каналі можна подивитися на приклад застосування Zustand. Краще один раз побачити, ніж один раз прочитати :)
Популярність
Якщо ви вперше почули про цю бібліотеку, то її популярність може вас здивувати. Майже три мільйони щотижневих завантажень на npm та понад 41 000 зірочок на GitHub. Глянувши на npm trends, побачимо, що за рівнем популярності Zustand практично досягла Redux Toolkit.
Альтернативи
Уже згадував про React Context — він здається чудовим рішенням та й доступний одразу «з коробки». Проте його використання може призвести до проблем з продуктивністю, оскільки компоненти будуть ререндеритися при зміні даних саме в Context, навіть якщо компонент безпосередньо не використовує ці дані.
Компонент заререндерився — всі дочірні компоненти також треба відрендерити. Підписуватися на конкретні поля в React Context не можна. Окремою морокою буде написання методів зміни цього стейту. Тут в пригоді будуть знання Redux або хоча б роботи з useReducer.
Можна використати Redux, але він може виявитись складним для вивчення і має багато boilerplate коду. Не всі хочуть тягнути Redux у маленькі або PET-проєкти. Рішенням міг би стати Redux Toolkit, але він все ще монструозний і наслідує Redux, необхідно описувати редюсери тa екшени.
Єдиний стор може бути не оптимальним рішенням, коли ви плануєте реалізувати модульність і хотіли б розбити логіку. Принцип Single Responsibility ніхто ще не скасовував.
Є інші рішення, такі як MobX або React Signals, але вони також мають свої недоліки. Обидва реалізовують реактивність за допомогою Observable. Обʼєм boilerplate коду мінімальний, особливо в React Signals.
Signals є новим підходом і не всім він подобається, оскільки в React вони мутабельні і дехто називає це антипатерном. До того ж не підтримується Flux-архітектура. MobX просто не дуже популярний, хоч і зручний у використанні.
Згадувати Recoil, Valtio або GraphQL Apollo не бачу сенсу. Recoil — це, як на мене, знущання. Ще не бачив жодного задоволеного ним розробника. GraphQL вимагає відповідно реалізацію цього GraphQL на клієнті та на сервері. Та й хайп навколо нього уже зійшов.
Що пропонує Zustand
Це простий у використанні стейт-менеджер, який вирішує багато проблем. Zustand дозволяє створювати декілька сторів для модульності, використовує хуки для зручного доступу до стану та оновлення компонентів і не вимагає провайдера або контексту. Реалізовані slices — використання лише тих даних стору, що необхідні конкретному компоненту, і при зміні інших даних не викликатимуться зайві рендери.
Zustand, як і Redux, підтримує концепцію імутабельного стану, що є ключовим аспектом ефективного управління станом в React-застосунках. Його синтаксис простий і легкий для вивчення, що робить його ідеальним вибором як для початківців, так і для досвідчених розробників. Якщо у вас є досвід роботи з Redux і ви його фанат — то і тут, за бажання, можна написати dispatch-функцію та зробити reducer. Підхід буде дуже схожий на Redux.
Хоч Zustand і використовує хуки для доступу до стору — ви можете застосовувати його не лише в межах компонента, а й в окремих функціях. Тобто, якщо вам потрібно написати якусь утиліту, ви можете використати цей хук, просто отримавши стан з нього. Немає жодних обмежень щодо використання хуків, вам не потрібно дотримуватися жодних правил.
Практика
Щоб розпочати роботи із цією бібліотекою, раджу подивитися їхнє демо. Весь стор і логіка його зміни реалізовані кількома рядками.
Перш за все необхідно імпортувати функцію create
.
import { create } from 'zustand'
Тут можна побачити ще один плюс бібліотеки — додаткові бібліотеки чи модулі їй не потрібні. З MobX, наприклад, потрібно ставити ще mobx-react-lite
, з Redux (Redux Toolkit) часом треба redux-thunk
або redux-saga
. Розмір бібліотеки Zustand можна глянути на Bundlephobia — 1,2 кб.
Наступним кроком створюється сам стор. Важливо зазначити назву — вона має розпочинатися префіксом use
, адже це все ж таки React-хук.
const useStore = create((set) => ({ count: 1, inc: () => set((state) => ({ count: state.count + 1 })), }))
Функція set, яка передається першим параметром в колбек для create
, працює схоже на стару-добру setState
в класових React-компонентах. Потрібно передати поля, які бажаєте змінити, й вони будуть змерженими з поточним стейтом. Нічого не перетинається і не треба використовувати Spread syntax.
Саме ж використання стору нічим не відрізняється від кастомного хука.
const { count, inc } = useStore()
Важливо зазначити, що в цьому прикладі не використовуються слайси та відбувається «підписка» на весь стор. Для покращення продуктивності, потрібно брати лише необхідні дані, наприклад:
const count = useStore((state) => state.count)
Бонус
Devtools, які так необхідні для відстежування змін в сторі, тестуванні та дебагінг, також присутні. Ще й вирішили не ускладнювати собі та нам життя — взяли цей інструмент в Redux.
Можливість локального зберігання стору реалізована за допомогою persist
middleware.
Отже, у 2024 році Zustand може стати ідеальним стейт-менеджером для React-застосунків завдяки своїй простоті, ефективності та зручності використання. Його популярність, яка швидко зростає, свідчить про те, що він вже зарекомендував себе як потужний інструмент.
Поки що не чув негативних відгуків про Zustand. Діліться враженнями в коментарях. Також цікаво дізнатися, який стейт-менеджер використовуєте ви. У моєму Telegram-каналі є опитування з усіх найпопулярніших рішень.
16 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів