State Management in React mit zustand

State Management in React mit zustand

  • Beitrags-Autor:Timon G
  • Beitrags-Kommentare:1 Kommentar

Wenn man in seiner React App an den Punkt gelangt, an dem das State Management komplexer wird, steht man schnell vor der Wahl einiger Bibliotheken wie react-redux, mobx oder akita.
In diesem Artikel möchte ich eine der State Management Varianten vorstellen: zustand.
Ich persönlich bin seit dem Wechsel von NGXS in Angular zu React ein großer Fan davon. Trotz der geringen Größe (Unter 1kB minified + gezipped) bietet zustand alle Notwendigkeiten für komplexes State Management. Die komplette API basiert auf React Hooks, ist einfach zu nutzen und kann mit eigenen Middlewares angepasst werden.

Nutzung

Als Beispiel habe ich eine kleine React App gebaut, die eine Art „Website-Editor“ darstellen soll: CodeSandbox App

Sie besteht aus den folgenden Bereichen:

  • Form: Das Formular um Änderungen einzugeben
  • Preview: Eine Live Vorschau der eingegebenen Änderungen

In so einem typischen Szenario wird ein globaler State benötigt, der als „single source of truth“ agiert. So können andere Komponenten sich auf den globalen State verlassen und zusätzlich wird vermieden den State über Props an Komponenten weiterzureichen.

Da in diesem Beispiel zustand als State Management System genutzt wird, kann hier auch auf die Umhüllung von einem Context Provider verzichtet werden.  

Um zustand einzusetzen muss in der App ein neuer Store als Hook erstellt werden. In meinem Fall habe ich eine neue Datei erstellt (app.state.js), die folgende Funktion exportiert.

import create from "zustand";

export const useAppStore = create((set) => ({
  title: "MyProduct - 30 day free trial",
  description: "Lorem ipsum dolor sit amet...",
  setTitle: (title) => set((state) => ({ title })),
  setDescription: (description) => set((state) => ({ description }))
}));

Mit import create from "zustand" wird hier die Funktion zum Erstellen eines Stores von zustand importiert und dann in der Zeile darunter aufgerufen. set ist eine Funktion, die zustand mitreicht, um den State zu modifizieren. Zusätzlich kann man noch get hinzufügen, wenn man den gesamten State später benötigt.

In der create Funktion kann nun der Inhalt des State definiert werden, wie z.B. die einzelnen Properties und Reducer Funktionen, um die Properties zu ändern. Reducer können natürlich auch asynchron sein, zustand ist das vollkommen egal.

Da es sich bei dem Store um eine Hook handelt, kann er auch normal in Komponenten genutzt werden. In der Form.js Komponente wird zum Beispiel der setTitle und setDescription Reducer genutzt, um neue Werte für den Titel und die Beschreibung zu setzen.

const setTitle = useAppStore((state) => state.setTitle);
const setDescription = useAppStore((state) => state.setDescription);

const handleTitleChange = (ev) => {
  setTitle(ev.target.value);
};

const handleDescriptionChange = (ev) => {
  setDescription(ev.target.value);
};

Erst wird über die vorhin definierte Hook useAppStore der jeweilige Reducer selektiert. Danach kann dieser mit dem neuen Wert aufgerufen werden.

Um am Schluss die Daten in der Vorschau anzuzeigen, wird genau wie beim Formular die useAppStore Hook genutzt. Dabei werden statt den Reducern einfach die Properties selektiert.

const title = useAppStore((state) => state.title);
const description = useAppStore((state) => state.description);

Middlewares

Wie bereits angesprochen erlaubt zustand auch die Nutzung von sogenannten Middlewares. Diese liegen als Schichten um den State und erlauben zusätzliche Eingriffe, wie beispielsweise das Loggen von State Änderungen oder das Persistieren des State.

Ein Beispiel ist eine Logging Middleware, die den neuen State als Parameter erhält und in der Konsole ausgibt.

const log = config => (set, get, api) => config(args => {
  console.log("  applying", args)
  set(args)
  console.log("  new state", get())
}, get, api)

Um diese Middleware zu nutzen muss sie danach noch in der create Funktion aufgerufen werden:

const useAppStore = create(
  log(
    (set) => ({
     	…
    }),
  ),
)

Bonus

Wer zustand ohne React nutzen möchte hat Glück, denn zustand stellt auch eine Vanilla JS API bereit, die dann aber ohne Hooks funktioniert.

import create from 'zustand/vanilla'
const store = create(() => ({ ... }))
const { getState, setState, subscribe, destroy } = store

Wer ein Fan von Redux ist, kann zusätzlich noch zustand mit den Redux-Dev-Tools verknüpfen und seine Reducer in Redux Syntax konvertieren. Mehr dazu hier https://github.com/pmndrs/zustand#cant-live-without-redux-like-reducers-and-action-types

Wenn diese Bibliothek dein Interesse geweckt hat und du mehr über zustand erfahren möchtest, empfehle ich die offizielle Dokumentation auf GitHub

Bild: https://github.com/pmndrs/zustand

Dieser Beitrag hat einen Kommentar

Schreibe einen Kommentar