Skip to main content

Що таке middleware у Zustand?

У Zustand термін middleware (проміжне ПЗ) означає функцію-обгортку, яка розширює поведінку стора, додаючи додаткову логіку між зміною стану (set) і самим її застосуванням.

Якщо простіше:

Middleware у Zustand - це плагіни, які "вбудовуються" в store і додають нові можливості: збереження, логи, devtools, іммутабельність тощо.


Як це працює

Коли ти створюєш store:

javascript
import { create } from 'zustand' const useStore = create((set) => ({ count: 0, inc: () => set((s) => ({ count: s.count + 1 })), }))

Zustand дозволяє обгорнути цей "чистий" store функцією-міддлварою, щоб змінити або доповнити його поведінку:

javascript
import { devtools } from 'zustand/middleware' const useStore = create( devtools((set) => ({ count: 0, inc: () => set((s) => ({ count: s.count + 1 })), })) )

Тепер Zustand підключається до Redux DevTools, і ти можеш відстежувати стан у браузері.


Популярні middleware у Zustand

MiddlewareПризначення
devtoolsінтеграція з Redux DevTools для відлагодження
persistзберігає стан у localStorage, sessionStorage або IndexedDB
immerдозволяє змінювати стан "імперативно" через draft (як у Redux Toolkit)
subscribeWithSelectorпідписка тільки на потрібні поля (глибока селективність)
combineдопомагає об'єднувати декілька зрізів стану в один store
reduxемулює Redux-подібну поведінку з actions і reducers

Приклади використання

1. persist

Зберігає стан між перезавантаженнями сторінки:

javascript
import { create } from 'zustand' import { persist } from 'zustand/middleware' const useAuthStore = create( persist( (set) => ({ user: null, setUser: (user) => set({ user }), logout: () => set({ user: null }), }), { name: 'auth-storage' } // ключ у localStorage ) )

Тепер дані автоматично зберігатимуться в localStorage.


2. devtools

Додає інтеграцію з Redux DevTools:

javascript
import { create } from 'zustand' import { devtools } from 'zustand/middleware' const useCounterStore = create( devtools((set) => ({ count: 0, inc: () => set((s) => ({ count: s.count + 1 })), })) )

Тепер можна відкривати DevTools і бачити всі зміни стану.


3. immer

Дозволяє використовувати мутабельний стиль оновлення (через draft):

javascript
import { create } from 'zustand' import { immer } from 'zustand/middleware/immer' const useTodoStore = create( immer((set) => ({ todos: [], addTodo: (text) => set((state) => { state.todos.push({ text, done: false }) }), })) )

Тут можна "змінювати" масив напряму, ніби це звичайний JS-об'єкт - під капотом Zustand робить іммутабельне копіювання.


4. Комбінування middleware

Можна використовувати декілька міддлвар одночасно - просто вкладай їх:

javascript
import { create } from 'zustand' import { devtools, persist } from 'zustand/middleware' const useStore = create( devtools( persist( (set) => ({ theme: 'light', toggleTheme: () => set((s) => ({ theme: s.theme === 'light' ? 'dark' : 'light' })), }), { name: 'theme-storage' } ) ) )

Як middleware влаштоване всередині

Middleware - це функція вищого порядку:

javascript
type Middleware = (createState: StateCreator) => StateCreator

Вона приймає createState (твою функцію, що створює store) і повертає нову функцію, яка обгортає або змінює поведінку set, get, subscribe.

Приклад власного middleware:

javascript
const logger = (config) => (set, get, api) => config( (args) => { console.log('Before:', get()) set(args) console.log('After:', get()) }, get, api )

Підсумок

Що робить middlewareПриклад
Додає нові функції в storepersist, devtools, immer
Перехоплює і змінює set()логування, фільтрація
Розширює API стораметоди на кшталт .persist.rehydrate()
Можна комбінуватиdevtools(persist(...))

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.