ProNextJS
    State Management with Next.js App RouterLevel up with State Management with Next.js App Router

    I respect your privacy. Unsubscribe at any time.

    This is a free tutorial

    In exchange for your email address, you'll get full access to this and other free ProNextJS tutorials.

    Why? First and foremost, your inbox allows us to directly communicate about the latest ProNextJS material. This includes free tutorials, NextJS Tips, and periodic update about trends, tools, and NextJS happenings that I'm excited about.

    In addition to the piles of free NextJS content, you'll get the earliest access and best discounts to the paid courses when they launch.

    There won't be any spam, and every email you get will have an unsubscribe link.

    If this sounds like a fair trade, let's go!

    solution

    Pass Data from the Server to the Client Context

    Jack HerringtonJack Herrington

    The first action takes place in our Layout component.

    We already have created a cart in there, so now we'll add it to the CartProvider:

    const cart = await getCart()
    ...
    
    // inside the return
    <CartProvider cart={cart}>
      <Header clearCartAction={clearCartAction} />
      ...
    

    Now we need to update the CartProvider to accept the cart property.

    Updating the Cart Provider

    In the CartProvider inside of CartContext.tsx, we'll introduce a new property called cart, which is then mapped to initialCart. This initialCart is passed on to our useCartState hook.

    // In CartContext.tsx
    const CartProvider = ({
    	cart: initialCart,
    	children,
    }: {
    	cart: Cart,
    	children: React.ReactNode,
    }) => {
    	const [cart, setCart] = useCartState();
    
    	return (
    		<CartContext.Provider value={[cart, setCart]}>
    			{children}
    		</CartContext.Provider>
    	);
    };
    

    The useCartState takes the initialCart and uses it as its initial value.

    Checking Our Work

    After saving these changes, refreshing the app starts the cart count at two, confirming that we have the data we expect from the initial render.

    Checking the rendered HTML with "View Source", we can see further proof that everything is working.

    Note the HTML that contains the cart count of 2:

    <span class="text-xl font-bold leading-10 text-gray-100">2</span>
    

    Even though the Header is a client component, it does render on the server.

    Further down in the rendered html is the React Server Component code that connects the server with the client.

    During client hydration, React serializes the properties passed from an RSC into a client component. This ensures that the cart context remains consistent between the server and client.

    We can see the encoded JSON for the initial cart data:

    {\"cart\":{\"products\":[{\"id\": 1,\"name\":\"Castle
    T-Shirt\",\"image\":\"/castle-t-shirt.jpg\",\"price\":25},{\"id\":2,\"name\":\"Dragon
    T-Shirt\",\"image\":\"/dragon-t-shirt.jpg\", \"price\":25}]}}
    

    Recapping the Context Initialization

    Our context is being initialized because of the setup we did in the Layout component.

    In the Layout, which is a React Server Component, we pass the cart as a prop to the CartContext, which is a Client Component.

    When you pass properties from an RSC into a client component, they are serialized by React.

    In the next exercise, we'll wrap up our React state implementation of our ecommerce app by adding the product reviews functionality.

    Transcript

    I've copied the contents of the cart context directory into the cart context with initial state directory, install my modules, and run it, and I'm ready to go. So let's go take a look over at our layout because that's actually where all of the action is going to happen. So in the layout, we have the current cart, but we're just ignoring it.

    So what we want to do is we want to go and send that cart to our cart provider. Of course, it doesn't know it needs a cart. So let's go over into our cart provider and upgrade that. So we're going to take a new property called cart, and then I'll take cart and map it to initial cart, and then I'll pass that onto our useCartState hook.

    UseCartState will take that initial cart, and then use it as the initial value. Let's save, and let's try it out. Now when I hit refresh, it starts at two in our cart context, and I bring it up, we've got our cart context, we're good to go from the initial render.

    So actually, let's go take a look at the ViewPageSource. So we can see that two hidden in all of the HTML, and that two from the server tells us that we are properly initializing that cart context on the server with that cart. So that on the initial server render,

    even though it is a client component, it does render on the server, we're getting the correct cart count right there. You can also see if you scroll a little bit further down in your HTML, the RSC code that connects the server with the client. You can actually see that the cart is being serialized by

    React and then passed on to the client. Then during client hydration, that cart is then hydrated on a client so that the context on the server matches the context on the client. Now all this is being done because over here in the layout,

    we are passing that cart as a property from the RSC into that cart context. When you pass properties from an RSC into a client component, they are serialized by React. So why don't you join me in the next exercise where we wrap up our React state implementation of

    our e-commerce app by adding the product reviews functionality.