CODELIVERY BLOG

Zustand – Co to jest? I czy to lepsze od Reduxa?

by | Apr 2, 2025 | Bez kategorii

Best Asset management alternatives in 2024

Table Of Content

Zustand w React: Prosty sposób na zarządzanie stanem bez Redux Toolkit?

Zarządzanie stanem aplikacji to jedno z kluczowych wyzwań w tworzeniu nowoczesnych interfejsów użytkownika. W ekosystemie React pojawiło się wiele bibliotek próbujących rozwiązać ten problem, a jedną z zyskujących popularność jest Zustand. W tym artykule przyjrzymy się bliżej tej bibliotece, jej zaletom i implementacji, a także dowiemy się, skąd pochodzi jej intrygująca nazwa.

Co to jest Zustand i jak działa w aplikacjach React?

Definicja i podstawowe założenia biblioteki Zustand

Zustand to minimalistyczna biblioteka do zarządzania stanem w aplikacjach React. Jej nazwa pochodzi z języka niemieckiego, gdzie “Zustand” oznacza “stan” (więcej o tym w dalszej części artykułu). Biblioteka została stworzona jako lżejsza alternatywa dla Redux, oferująca prosty interfejs API i mniejszą ilość kodu boilerplate.

Główne założenia Zustand to:

  • Minimalizm i prostota użycia
  • Brak Provider wrappers (w przeciwieństwie do Context API czy Redux)
  • Możliwość używania store poza komponentami React
  • Wsparcie dla middlewares
  • Automatyczna optymalizacja renderowania komponentów

Porównanie Zustand z Context API w React

Context API jest wbudowanym w React mechanizmem do przekazywania danych w drzewie komponentów bez konieczności przekazywania props na każdym poziomie. Jednak w porównaniu z Zustand, Context ma pewne ograniczenia:

  • Context powoduje renderowanie wszystkich komponentów konsumujących dany context przy każdej zmianie jego wartości
  • Tworzenie wielu contextów może prowadzić do tzw. “Provider Hell”
  • Zustand automatycznie optymalizuje rendering – aktualizowane są tylko komponenty używające zmienionych części stanu

Implementacja globalnego stanu za pomocą Zustand

Implementacja globalnego stanu w Zustand jest niezwykle prosta. Wystarczy zdefiniować store w jednym pliku:

javascriptCopy

import create from 'zustand' const useStore = create((set) 

=> ({ counter: 0, increaseCounter: () =>set((state) => ({ counter: state.counter + 1 })), decreaseCounter: () 

=> set((state) => ({ counter:state.counter - 1 })), resetCounter: () => set({ counter: 0 }), })) export default useStore;

A następnie używać go w komponentach:

javascriptCopy

import useStore from './store' function Counter() 

{ const { counter, increaseCounter,decreaseCounter, resetCounter } = useStore() return ( <div> <p>Counter: {counter}</p>

 <button onClick={increaseCounter}>+</button> <button onClick={decreaseCounter}>-</button> <button onClick={resetCounter}>Reset</button> </div> ) }

Zustand vs Redux – które rozwiązanie wybrać do zarządzania stanem?

Różnice w boilerplate pomiędzy Zustand a Redux

Jedną z głównych zalet Zustand jest minimalna ilość kodu potrzebna do implementacji zarządzania stanem. Porównajmy przykłady:

Redux Toolkit:

javascriptCopy

// slice.js import { createSlice } from '@reduxjs/toolkit' const counterSlice = createSlice({ name:'counter', initialState: { value: 0 }, reducers: { increment: (state) => { state.value += 1 },decrement: (state) => { state.value -= 1 }, reset: (state) => { state.value = 0 }, }, }) exportconst { increment, decrement, reset } = counterSlice.actions export default counterSlice.reducer // store.js import { configureStore } from '@reduxjs/toolkit' import counterReducer from './slice'export const store = configureStore({ reducer: { counter: counterReducer, }, }) // App.js import {Provider } from 'react-redux' import { store } from './store' function App() { return ( <Providerstore={store}> <Counter /> </Provider> ) } // Counter.js import { useSelector, useDispatch } from'react-redux' import { increment, decrement, reset } from './slice' function Counter() { const count = useSelector((state) => state.counter.value) const dispatch = useDispatch() return ( <div><p>Count: {count}</p> <button onClick={() => dispatch(increment())}>+</button> <button onClick={()=> dispatch(decrement())}>-</button> <button onClick={() => dispatch(reset())}>Reset</button> </div>) }

Zustand:

javascriptCopy

// store.js import create from 'zustand' const useStore = create((set) => ({ counter: 0, increment:() => set((state) => ({ counter: state.counter + 1 })), decrement: () => set((state) => ({ counter:state.counter - 1 })), reset: () => set({ counter: 0 }), })) // Counter.js import useStore from'./store' function Counter() { const { counter, increment, decrement, reset } = useStore() return (<div> <p>Count: {counter}</p> <button onClick={increment}>+</button> <button onClick={decrement}>-</button> <button onClick={reset}>Reset</button> </div> ) }

Jak widać, Zustand wymaga znacznie mniej kodu i nie potrzebuje dodatkowych wrapperów, akcji czy reducerów.

Performance i wydajność Zustand w porównaniu do Redux

Zustand oferuje lepszą wydajność niż Redux w wielu scenariuszach:

  1. Granularne aktualizacje: Zustand automatycznie aktualizuje tylko komponenty, które faktycznie używają zmienionych części stanu.
  2. Mniejszy narzut obliczeniowy: Dzięki prostocie biblioteki, Zustand ma mniejszy wpływ na ogólną wydajność aplikacji.
  3. Brak Provider: Eliminacja Provider wrappers oznacza, że Zustand nie powoduje niepotrzebnych renderowań wynikających z kontekstu.
  4. Lazy initialization: Zustand wspiera leniwe inicjalizowanie stanu, co może znacznie poprawić początkową wydajność aplikacji.

Kiedy wybrać Zustand zamiast Redux Toolkit?

Zustand może być lepszym wyborem niż Redux w następujących sytuacjach:

  • Mniejsze i średnie aplikacje, gdzie pełna architektura Reduxa może być zbyt rozbudowana
  • Projekty, gdzie kluczową kwestią jest minimalizacja boilerplate’u
  • Aplikacje wymagające wysokiej wydajności i optymalizacji renderowania
  • Sytuacje, gdy potrzebujemy użyć stanu poza komponentami React
  • Gdy zależy nam na szybkiej implementacji i mniejszej krzywej uczenia

Z drugiej strony, Redux może być lepszym wyborem dla bardzo dużych aplikacji z rozbudowaną logiką biznesową, gdzie docenimy jego narzędzia do debugowania i ścisłą strukturę.

Jak zaimplementować store w Zustand?

Tworzenie i konfiguracja store w aplikacji React

Podstawowy store w Zustand można utworzyć w kilku prostych krokach:

javascriptCopy

import create from 'zustand' // Definiujemy store const useStore = create((set) => ({ // Stan początkowy user: null, isLoading: false, error: null, // Akcje modyfikujące stan login: async(credentials) => { set({ isLoading: true, error: null }); try { const user = awaitapiLogin(credentials); set({ user, isLoading: false }); } catch (error) { set({ error:error.message, isLoading: false }); } }, logout: () => set({ user: null }), })) export defaultuseStore;

W powyższym przykładzie tworzymy store z stanem użytkownika i funkcjami do logowania i wylogowywania.

Zarządzanie złożonym stanem przy użyciu Zustand

Dla bardziej złożonych przypadków, Zustand oferuje kilka przydatnych wzorców:

Łączenie wielu store’ów:

javascriptCopy

import create from 'zustand' const useUserStore = create((set) => ({ user: null, login: (user) =>set({ user }), logout: () => set({ user: null }), })) const useCartStore = create((set) => ({ items:[], addItem: (item) => set((state) => ({ items: [...state.items, item] })), clearCart: () => set({items: [] }), })) // Komponent używający obu store'ów function Profile() { const user =useUserStore((state) => state.user) const items = useCartStore((state) => state.items) return (<div> <h1>Welcome, {user?.name}</h1> <p>You have {items.length} items in your cart</p> </div> ) }

Integracja Zustand z komponentami React

Integracja Zustand z komponentami React jest niezwykle prosta. Store używany jest jako hook, który można selektywnie dostosować do potrzeb danego komponentu:

javascriptCopy

import useStore from './store' // Pobranie całego stanu function FullStateComponent() { const state = useStore() return <div>{JSON.stringify(state)}</div> } // Selektywne pobieranie części stanufunction CounterComponent() { const counter = useStore((state) => state.counter) return<div>Counter: {counter}</div> } // Pobieranie akcji function ActionComponent() { const increment =useStore((state) => state.increment) return <button onClick={increment}>Increase</button> } // Memoizacja selektorów dla lepszej wydajności function MemoizedComponent() { const items = useStore((state) => state.items, (prev, next) => prev.length === next.length ) return <div>Items count:{items.length}</div> }

Zustand automatycznie optymalizuje renderowanie – komponent zostanie przerenderowany tylko wtedy, gdy wartość zwracana przez selektor ulegnie zmianie.

Dlaczego nazwa “Zustand” i co oznacza w języku niemieckim?

Pochodzenie nazwy i tłumaczenie słowa “Zustand” na polski

Nazwa “Zustand” pochodzi z języka niemieckiego. Tłumaczenie na polski słowa “Zustand” to po prostu “stan” – co doskonale oddaje przeznaczenie biblioteki.

W języku niemieckim “Zustand” (często pisane z małej litery jako “zustand”) opisuje kondycję, stan lub sytuację czegoś. Forma liczby mnogiej to “Zustände”. W słowniku online PONS można znaleźć tłumaczenie hasła “zustand” z niemieckiego na polski.

Kilka przykładowych zdań ze słowem “Zustand”:

  • “In gutem Zustand” – “W dobrym stanie”
  • “Den Zustand verbessern” – “Poprawić stan”
  • “Zustand des Gebäudes” – “Stan budynku”

Warto zauważyć, że wiele bibliotek JavaScript ma nazwy inspirowane różnymi językami lub konceptami – Zustand jest tego doskonałym przykładem.

Wymowa “Zustand” i formy pokrewne

Wymowa słowa “Zustand” w języku niemieckim to mniej więcej “coo-shtand” z akcentem na pierwszą sylabę. W transkrypcji fonetycznej zapisywane jest jako /ˈtsuːʃtant/.

Pokrewne formy i wyrażenia obejmują:

  • “zustande kommen” – “dojść do skutku”
  • “Istzustand” (lub “Ist-Zustand”) – “stan faktyczny/obecny”
  • “dadurch zustande” – “w ten sposób powstało”

Praktyczne zastosowania Zustand w aplikacjach React

Zustand doskonale sprawdza się w wielu scenariuszach działania aplikacji React:

  1. Zarządzanie autentykacją użytkowników Przechowywanie stanu logowania, danych użytkownika i tokenów.
  2. Koszyki zakupowe w e-commerce Obsługa dodawania, usuwania przedmiotów i kalkulacji cen.
  3. Filtrowanie i sortowanie list danych Zarządzanie preferencjami użytkownika dotyczącymi wyświetlania danych.
  4. Formularze wielokrokowe Przechowywanie danych pomiędzy kolejnymi krokami formularza.
  5. Obsługa motywów i preferencji użytkownika Przełączanie między trybem jasnym i ciemnym, zapisywanie ustawień.

Dzięki prostocie API, Zustand można łatwo zintegrować z istniejącymi aplikacjami, a jego niewielki rozmiar nie zwiększa znacząco rozmiaru aplikacji.

Podsumowanie

Zustand stanowi interesującą alternatywę dla bardziej rozbudowanych rozwiązań jak Redux czy Redux Toolkit. Jego główne zalety to prostota, minimalna ilość kodu boilerplate i dobra wydajność. Jest to biblioteka, która doskonale wpasowuje się w filozofię React – prostota, kompozycja i wydajność.

Nazwa “Zustand” (stan po niemiecku) idealnie oddaje przeznaczenie biblioteki. Jeśli szukasz prostego, ale potężnego narzędzia do zarządzania stanem w aplikacjach React, warto rozważyć Zustand jako alternatywę dla bardziej złożonych rozwiązań.

Dzięki elastycznemu API, Zustand można dostosować do różnych potrzeb – od prostych liczników po złożone aplikacje biznesowe. Biblioteka ta udowadnia, że zarządzanie stanem w React nie musi być skomplikowane i obciążone nadmierną ilością kodu.

Let’s deliver great things together.

Reach out to discuss your next big idea.

Get in Touch: Leave Your Message Here!

In 2012, I invested in a project led by Marek and Dominik. Throughout the investment period, the company demonstrated creativity, and their pivots were successfully implemented by the team.

Rafał Brzoska

CEO at InPost

Agreement