Best practices with global state management and SSR
Answered
American black bear posted this in #help-forum
American black bearOP
Hey everyone!
I'd like to hear your thoughts on how you handle this kind of situation.
Basically, I have a page.tsx rendered on the server side and two components rendered on the client side on this page.
The page fetches the information and passes it to the client components using props. Once the information is available, I use a custom store with Zustand to set the data and share it with the other child components.
However, there's a small delay between fetching the data -> passing it to the client component -> setting it in the store.
What would you do? Prop drilling? Skeleton?
I'd like to hear your thoughts on how you handle this kind of situation.
Basically, I have a page.tsx rendered on the server side and two components rendered on the client side on this page.
The page fetches the information and passes it to the client components using props. Once the information is available, I use a custom store with Zustand to set the data and share it with the other child components.
However, there's a small delay between fetching the data -> passing it to the client component -> setting it in the store.
What would you do? Prop drilling? Skeleton?
Answered by Double-striped Thick-knee
import { cache } from "react";
import { getUserData } from ".."
const getData = cache(getUserData)
export default async function ServerComponent() {
const data = await getData();
return (
<div>
<ClientComponent data={data} />
<AnotherServerComponent />
</div>
);
}
async function AnotherServerComponent() {
const data = await getData();
return (
<div>
<AnotherClientComponent data={data} />
<AnotherClientComponent2 data={data} />
</div>
);
}if your use-case is something else, there's no other way I think
46 Replies
@American black bear so you are selecting some data piece from the global store in your child components?
American black bearOP
let me show you an example
// app/example/page.tsx
export default async function Page() {
const something = await fetchSomething()
return (
<div>
<ChildOne something={something} />
<ChildTwo something={something} />
</div>
)
}// app/example/ChildOne.tsx
'use client'
export default function ChildOne({something}) {
return (
<div>
<h3>{something.title}</h3>
</div>
)
}'use client'
export default function ChildOne({ something }) {
const { setSomething } = useSomethingStore()
useEffect(() => {
setSomething(something)
}, [])
if (!something) return <h1>loading...</h1>
return (
<div>
<OtherComponent />
<OtherComponent2 />
</div>
)
}I think now it's easy to understand
so basically OtherComponent and OtherComponent2 are not waiting via props the data, it's actually getting this info from the store
yeah, so in OtherComponent and OtherComponent2
what do you exactly do with the store? do you make any api fetch again?
or just process the data from the store and display?
@James4u what do you exactly do with the store? do you make any api fetch again?
American black bearOP
no, just showing some data
@James4u or just process the data from the store and display?
American black bearOP
yup
that's it
however there is a delay between this process of fetching data, receiving data on the client side and storing it
Then I think your OtherComponent and OtherComponent2 can be server components
and fetch data directly inside those components and process on the server side
American black bearOP
it can't be
because there are interactions
I see, then move your client side logics into client component and then import that component in server component
American black bearOP
yeah but what is the difference? this is exactly what I am doing now
yeah, no much difference but my point here is why redux? I think you are processing data on the client side?
@James4u yeah, no much difference but my point here is why redux? I think you are processing data on the client side?
American black bearOP
to avoid prop drilling and because I need to modify the data according to the user interaction
@American black bear to avoid prop drilling and because I need to modify the data according to the user interaction
yeah, so fetch data in the server component and pass it to the child component - there is no props drilling then
@James4u yeah, so fetch data in the server component and pass it to the child component - there is no props drilling then
American black bearOP
ok, so if I send it to the client component it means that the first child from the parent also needs to share the prop to their child...
then we have a prop drilling
I thought it was just a client component that renders the data - as you said you are just displaying them.
but if you have some components deeply inside, you need context or redux maybe
but if you have some components deeply inside, you need context or redux maybe
American black bearOP
yeah and I have that
I have zustand
but it doesn't change anything because I still can see the delay of setting the value of the server using the first client child
it should be instant
@American black bear js
// app/example/page.tsx
export default async function Page() {
const something = await fetchSomething()
return (
<div>
<ChildOne something={something} />
<ChildTwo something={something} />
</div>
)
}
js
// app/example/ChildOne.tsx
'use client'
export default function ChildOne({something}) {
return (
<div>
<h3>{something.title}</h3>
</div>
)
}
js
'use client'
export default function ChildOne({ something }) {
const { setSomething } = useSomethingStore()
useEffect(() => {
setSomething(something)
}, [])
if (!something) return <h1>loading...</h1>
return (
<div>
<OtherComponent />
<OtherComponent2 />
</div>
)
}
I think now it's easy to understand
American black bearOP
that's an example but my code is working just liek this
and the setSomething in the first child has a delay to execute
const { setSomething } = useSomethingStore()
useEffect(() => {
setSomething(something)
}, [])is this just storing the data? without heavy calculation?
American black bearOP
yes
it's a simple useEffect
storing the data
that's why I don't really understand what's going on 

Double-striped Thick-knee
I don't think there's a way to render data instantly without prop drilling,
you can read this: https://github.com/vercel/next.js/discussions/45543
you can also use reacts cache function to refetch data inside multiple server components
you can read this: https://github.com/vercel/next.js/discussions/45543
you can also use reacts cache function to refetch data inside multiple server components
the point is that, his components are not server components
American black bearOP
exactly
the child components are actually client-side because they need user interaction...
@American black bear the child components are actually client-side because they need user interaction...
Double-striped Thick-knee
is there any way you can render those client components inside a server component?, then you could refetch again and pass it down.
American black bearOP
maybe
Double-striped Thick-knee
import { cache } from "react";
import { getUserData } from ".."
const getData = cache(getUserData)
export default async function ServerComponent() {
const data = await getData();
return (
<div>
<ClientComponent data={data} />
<AnotherServerComponent />
</div>
);
}
async function AnotherServerComponent() {
const data = await getData();
return (
<div>
<AnotherClientComponent data={data} />
<AnotherClientComponent2 data={data} />
</div>
);
}if your use-case is something else, there's no other way I think
Answer
@Double-striped Thick-knee ts
import { cache } from "react";
import { getUserData } from ".."
const getData = cache(getUserData)
export default async function ServerComponent() {
const data = await getData();
return (
<div>
<ClientComponent data={data} />
<AnotherServerComponent />
</div>
);
}
async function AnotherServerComponent() {
const data = await getData();
return (
<div>
<AnotherClientComponent data={data} />
<AnotherClientComponent2 data={data} />
</div>
);
}
if your use-case is something else, there's no other way I think
American black bearOP
but I need the user interaction to change some specific data. I don't think I can change the data on the client side and make the server see that and make the necessary request. is it possible?
@American black bear but I need the user interaction to change some specific data. I don't think I can change the data on the client side and make the server see that and make the necessary request. is it possible?
Double-striped Thick-knee
you can refresh the path after modifying the data.
@James4u ahhhhh - by interaction, did you mean that?
American black bearOP
user selecting a number, opening the drawer, selecting something else, etc...