Best way to initialize data in next js app router with zustand

1 week ago 11
ARTICLE AD BOX

your approach is basically correct. 🙂
Fetch once at the top, hydrate a global store, let all cards subscribe to it.
I’d just tweak how you fetch, not the whole idea.

In the App Router you don’t need a server action for the initial read. your layout.tsx is already a server component, so you can

import { FavoritesHydrator } from '@/components/favorites-hydrator' import { getUserFavorites } from '@/lib/favorites' export default async function RootLayout({ children }) { const favorites = await getUserFavorites() // DB/API on the server return ( <html> <body> <FavoritesHydrator initialFavorites={favorites}> {children} </FavoritesHydrator> </body> </html> ) }

then

'use client' import { useEffect } from 'react' import { useFavoritesStore } from '@/stores/favorites' export function FavoritesHydrator({ initialFavorites, children }) { const setFavorites = useFavoritesStore(s => s.setFavorites) useEffect(() => { setFavorites(initialFavorites) }, [initialFavorites, setFavorites]) return children }

And cards just do:

const isFav = useFavoritesStore(s => s.ids.includes(storeId))

Now every place that renders that store will stay in sync automatically.

Is fetching in the layout “bad” / blocking?
Not really. Server render has to wait for user favourites somewhere anyway. Doing it in the root layout means:

one server fetch instead of many client fetches,

no extra round-trip,

less chance of “flash” while favourites load.

Read Entire Article