How Not to Redraw the Entire Application?
One of the main mistakes when working with global state is " greedy " subscription.
1. The " Omnivorous " Component Problem
If you write in a component like this:
const state = useStore(); // You subscribed to the ENTIRE object
Your component becomes extremely " sensitive " . If a product price changes in the cart, and your component only shows the user's name — it will still redraw. In large applications, this leads to terrible lags.
2. Solution: Selectors (Surgical Precision)
A selector is a function that tells Zustand: " I only need this field, I don't care about the rest " .
// Component redraws ONLY if name changes
const userName = useStore((state) => state.user.name);
// Component redraws ONLY if product count changes
const cartCount = useStore((state) => state.items.length);
3. Destructuring Actions (Actions)
Functions that change state (e.g., addItem) are usually created once and never change. So they can be extracted via destructuring without harming performance:
const { addItem, removeItem } = useStore();
4. Middleware Superpowers
Zustand allows you to " upgrade " your store with ready plugins:
- Persist (Eternal storage): With one line of code, you can make the user's cart save in the browser. They can close the tab, turn off the computer, return in a week — and their products will still be there.
- Immer (Convenient mutation): Allows writing code in style
state.user.name = "Ivan"instead of complex constructions with the...operator. Under the hood, Immer itself will create the correct object copy.
5. Result: Professional Store
A good global state is a state that:
- Uses selectors to save resources.
- Logically divided into small parts (pieces or " slices " ).
- Doesn't store data that should be local or come from the server.
Zustand is freedom. It doesn't dictate strict rules but gives all tools for creating reactive and fast interfaces.