v28
v284w ago

zustand empty on inital render

Hello, I am currently using nextjs, trpc and zustand. I'm running into a problem where my zustand state is undefined on reacts inital render of the page. - I use trpc's prefetch function is a layout.tsx file to fetch data on the server, the data here is used on all routes within my /dashboard directory (this data is mainly for my dashboard sidebar - the data is being hydrated with trpcs hydrateclient comonent - i have a loading.tsx file to catch all trpc queries which are still running, if there are any a loading state will be displayed until all data is fetched.
export default async function Layout({ children, params }: Readonly<Props>) {
const { workspaceId } = await params;

await api.workspace.list.prefetch();
await api.connections.list.prefetch({ workspaceId });

return (
<HydrateClient>
<SidebarProvider>
<AppSidebar workspaceId={workspaceId} />
<main className="p-4 w-full">{children}</main>
</SidebarProvider>
<Toaster />
</HydrateClient>
);
}
export default async function Layout({ children, params }: Readonly<Props>) {
const { workspaceId } = await params;

await api.workspace.list.prefetch();
await api.connections.list.prefetch({ workspaceId });

return (
<HydrateClient>
<SidebarProvider>
<AppSidebar workspaceId={workspaceId} />
<main className="p-4 w-full">{children}</main>
</SidebarProvider>
<Toaster />
</HydrateClient>
);
}
Here is my workspace selector component, it is at the top of my dashboard sidebar and shares state between different pages on the dashboard, which is why i plan on using zustand. I am only using zustand for the current selected workspace at this time, as I know trpc has a built in state management cache for data retrieved from the server.
// workspaceId is passed in from my page layout.tsx file (it is obtained through the URL search params, eg: /dashboard/workspaceId/home
export const WorkspaceSelector = ({ workspaceId }: Props) => {
const { data: workspaces } = api.workspace.list.useQuery();
const {selectedWorkspace, setSelectedWorkspace} = selectedWorkspaceStore();

useEffect(() => {
const workspace = workspaces?.find((workspace) => workspace.id === workspaceId);
if (!workspace) return;
setSelectedWorkspace(workspace); // store the current selected workspace in zustand
}, [workspaceId, workspaces]);
// workspaceId is passed in from my page layout.tsx file (it is obtained through the URL search params, eg: /dashboard/workspaceId/home
export const WorkspaceSelector = ({ workspaceId }: Props) => {
const { data: workspaces } = api.workspace.list.useQuery();
const {selectedWorkspace, setSelectedWorkspace} = selectedWorkspaceStore();

useEffect(() => {
const workspace = workspaces?.find((workspace) => workspace.id === workspaceId);
if (!workspace) return;
setSelectedWorkspace(workspace); // store the current selected workspace in zustand
}, [workspaceId, workspaces]);
No description
1 Reply
v28
v28OP4w ago
The problem I am having is on the intial render, after the loading.tsx file has finished and the page content is visible, zustand store is still marked as undefined for the initial render of the page, causing quick data changes on the page from undefined -> selected value What can I do to stop this from happening? here is a visual of the issue:

Did you find this page helpful?