Bit of a complex issue
Unanswered
In&Out posted this in #help-forum
In&OutOP
I have been trying to make a page that has both server and client component, it's purpose is to, when I visit this specific page, it fetches data from an API and the data is put into a zustand store to be used on other components, but I cannot do this due to me having to use "use client" for zustand, how can I solve this issue?
9 Replies
Can you elaborate more? Normally, you can't interact with zustand store in server components, because they're not allowed to re-render
Therefore, you can only interact with it in client components.
To pre-fetch the data on the server, you may pass the result of fetch from a server component to a client component. Then, put the result into your store in a
Therefore, you can only interact with it in client components.
To pre-fetch the data on the server, you may pass the result of fetch from a server component to a client component. Then, put the result into your store in a
useEffect (in the client component).@fuma Can you elaborate more? Normally, you can't interact with zustand store in server components, because they're not allowed to re-render
Therefore, you can only interact with it in client components.
To pre-fetch the data on the server, you may pass the result of fetch from a server component to a client component. Then, put the result into your store in a `useEffect` (in the client component).
In&OutOP
Elaborate how? By the way, can you give me an example on how to do that please?
I guess this can be solved with me using server actions, but it's still in works
I can't understand what you are trying to achieve, are you trying to pre-fetch the data on server and store it into zustand store?
That's pretty simple.
1. Fetch your data in a server component, and pass it to a client component.
Then, we have 2 options:
- Update the value in a
However, it may cause a small flash because
- Use
This can ensure it's already defined in pre-render, which makes more sense.
1. Fetch your data in a server component, and pass it to a client component.
export async function ServerComponent() {
const data = await fetchData();
return <ClientComponent data={data} />
}Then, we have 2 options:
- Update the value in a
useEffectexport function ClientComponent({ data }: Props) {
const setData = useMyStore(s => s.setData);
useEffect(() => {
setData(data)
}, []);
return ...
}However, it may cause a small flash because
useEffect is only executed after small a delay (aka hydration). You can use this method if you don't mind about it.- Use
useRef insteadconst isMountedRef = useRef(false)
if (!isMountedRef.current) {
myStore.getState().setData(data)
isMountedRef.current = true
}This can ensure it's already defined in pre-render, which makes more sense.
@fuma That's pretty simple.
1. Fetch your data in a server component, and pass it to a client component.
tsx
export async function ServerComponent() {
const data = await fetchData();
return <ClientComponent data={data} />
}
Then, we have 2 options:
- Update the value in a `useEffect`
tsx
export function ClientComponent({ data }: Props) {
const setData = useMyStore(s => s.setData);
useEffect(() => {
setData(data)
}, []);
return ...
}
However, it may cause a small flash because `useEffect` is only executed after small a delay (aka hydration). You can use this method if you don't mind about it.
- Use `useRef` instead
tsx
const isMountedRef = useRef(false)
if (!isMountedRef.current) {
myStore.getState().setData(data)
isMountedRef.current = true
}
This can ensure it's already defined in pre-render, which makes more sense.
In&OutOP
Thank you mate, I'll try this
import { fetchGuild } from "@/components/utils/api";
import { useGuildStore } from "@/components/utils/contexts/GuildContext";
import { useEffect } from "react";
async function page({ params }: { params: any }) {
const guild = await fetchGuild(params.id);
const store = useGuildstore((state)=>state.base)
return (
<div className="page">
<div>Dashboard Page {guild.name}</div>
</div>
);
}
export default page;This is what I did before lol