Persist Sidebar Toggle State Across SSR and Client Hydration in React with Zustand?
I have a sidebar that users can toggle on and off. To persist the sidebar’s open/closed state across page reloads, I’m using Zustand with its persist middleware.
The challenge I’m facing is related to server-side rendering (SSR). Since the initial page is rendered on the server, the persisted state isn’t available during that phase. As a result, the sidebar always renders as open initially, and only after client-side hydration does Zustand apply the persisted state, causing a visible UI flicker.
I’m wondering if there’s a better approach to handle this, such as storing the sidebar state in cookies or another method that works seamlessly with SSR and hydration.
Has anyone dealt with this before? What are your recommendations or best practices for persisting UI state?
8 Replies
modern-teal•4w ago
shadcn sidebar recommends cookies here, although this example is for next.js
https://ui.shadcn.com/docs/components/sidebar#persisted-state
sidebar source: https://github.com/shadcn-ui/ui/blob/main/apps/v4/registry/new-york-v4/ui/sidebar.tsx#L86

modern-teal•4w ago
so in tanstack, maybe a server fn that reads the cookies server-side
you might wanna check out this thread: https://discord.com/channels/719702312431386674/1379400567104864328 not exactly the same problem, they are dealing with persisting dark mode, but it might help
other-emerald•4w ago
dark mode is very similar. I would persist this in local storage and read from localstorage before hydration.
continuing-cyanOP•4w ago
Thanks guys for the helpful suggestion
I was reading the Zustand docs and came across this
https://zustand.docs.pmnd.rs/integrations/persisting-store-data#how-can-i-check-if-my-store-has-been-hydrated
In my route component, I simply do not render the component if it’s not hydrated. This prevents flickering.
Oops, I notice that for a split second the page appears empty…
continuing-cyanOP•4w ago
other-emerald•4w ago
never used Zustand. just want to point out we have a dehydrate and hydrate method on router you can hook into.
this happens before rendering
other-emerald•4w ago
Oh. I missed that one. Where are the docs for it? For now I’m using a silly script injection to achieve that 😅
continuing-cyanOP•4w ago
Modified my implementation to make use of
hydrate
method available on router
That empty page problem no longer occurs