ProNextJS

    Now it’s your turn! Try solving this exercise.

    Run locally (recommended)

    Code

    Start by cloning the project repository and follow instructions in the README.

    Or in browser

    Open on Gitpod
    Continue
    exercise

    State Management with Zustand

    Jack HerringtonJack Herrington

    Implementing Zustand: A More Streamlined Approach to State Management

    Zustand (German for "state") is a popular state management library created by Daishi Kato. It offers a more streamlined approach compared to Redux, while following the same unidirectional model for managing state.

    For this exercise, we'll use Zustand to manage our application state. To get started, copy the 03-cart-context-with-initial-state directory and to a new 07-complete-zustand directory.

    My recommendation is to use two different stores for managing the state.

    Specifically, we'll use two different Zustand state hooks: one for managing the cart and another for reviews.

    Challenge

    After installing zustand, you'll need to remove the existing CartContext and ReviewContext objects and replace them each with their own Zustand store.

    In case you aren't familiar with Zustand, here's a quick overview of how it works.

    WARNING You cannot safely use Zustand hooks that are declared globally!

    Zustand hooks are normally global, but you can also create a Zustand hook and pass it around in a context, like so:

    "use client";
    import { useState, createContext, useContext } from "react";
    import { create } from "zustand";
    
    const createStore = (count: number) =>
    	create<{
    		count: number;
    		setCount: (cart: number) => void;
    	}>((set) => ({
    		count,
    		setCount(count: number) {
    			set({ count });
    		},
    	}));
    
    const CountContext = createContext<ReturnType<typeof createStore> | null>(null);
    
    export const useCount = () => {
    	if (!CartContext)
    		throw new Error("useCount must be used within a CountProvider");
    	return useContext(CountContext)!;
    };
    
    const CountProvider = ({
    	count,
    	children,
    }: {
    	count: number;
    	children: React.ReactNode;
    }) => {
    	const [store] = useState(() => createStore(count));
    	return (
    		<CountContext.Provider value={store}>{children}</CountContext.Provider>
    	);
    };
    
    export default CountProvider;
    

    In order to get the Zustand hook in a Client Component, follow this pattern:

    const useCountHook = useCount();
    

    From there you can call the hook like this:

    const { count, setCount } = useCountHook();
    

    The above could also be shortened to:

    const { count, setCount } = useCount()(); // remove "Hook" and add another "()"
    

    Zustand also allows you to use selectors like so:

    const count = useCount()((state) => state.count);
    

    The above will force a re-render only when the returned value from the selector changes.

    Transcript

    Zustand is a very popular state management library for my friend, Daishi Kato. It is a lot more streamlined than Redux, but it follows that same Redux unidirectional model, which makes it very popular. Of course, it's a curse and blessing for me because I have to say

    the word zustand all the time, and I think he just grabbed it from a grab bag of different words for the word state. Zustand in German means state. Okay, so what we're going to do

    is we're going to take the 03 cart context with initial state example and create 07 complete zustand and then implement the whole example in zustand. Now, I recommend using two different

    stores. Use that multi-store approach like we did with cart provider and with reviews provider. Use two different zustand state hooks to manage the state. Use one for the cart and then another for the reviews. If you have any questions about how to use zustand,

    please look in the resources associated with this video. Good luck.