How can I show a loading state in my client component while the server component updates?
Unanswered
Highlander posted this in #help-forum
HighlanderOP
i am familiar with the pattern of lifting state up to the URL so that the queryParams force some sort of refetch in the server component, but what patterns exist to show a loading state while the server component is re-fetching?
9 Replies
do you use server action?
HighlanderOP
the server page (e.g.
not sure if that answers your question! im relatively newer to the app router and the patterns that are "newer" in next14, so lmk if i should be learning about something else in particular
app/hello-world/[...thing]/page.tsx
) is calling a server function, e.g.export default async function Page({
params: { thing },
searchParams
}: PageProps) {
// this is a server action
const data = await getServerData(searchParams, thing)
return (
<ClientComponent data={data} />
)
}
not sure if that answers your question! im relatively newer to the app router and the patterns that are "newer" in next14, so lmk if i should be learning about something else in particular
you can use the [loading.tsx](https://nextjs.org/docs/app/api-reference/file-conventions/loading) to show a loading state for your page.
Your server request is one request from the client and the client will only see the clientcomponent (your children), after the serverside request is finished. So there isn't any way to serve it before. However: you can serve a different (loading) page to show a loading animation while the server gets the data (that's why I mentioned
Your server request is one request from the client and the client will only see the clientcomponent (your children), after the serverside request is finished. So there isn't any way to serve it before. However: you can serve a different (loading) page to show a loading animation while the server gets the data (that's why I mentioned
loading.tsx
)HighlanderOP
@B33fb0n3 interesting! does it allow for cases like this?
where i can show a loading state for just
export default async function Page({
params: { thing },
searchParams
}: PageProps) {
// this is a server action
const data = await getServerData(searchParams, thing)
return (
<>
<ClientComponent data={data} />
<AnotherClientComponent />
</>
)
}
where i can show a loading state for just
ClientComponent
? or does the loading state show for the entire page? (this is a very simplified example ofc)Your server request is one request from the client and the client will only see the clientcomponent (your children), after the serverside request is finished. So there isn't any way to serve it before. However: you can serve a different (loading) page to show a loading animation while the server gets the data (that's why I mentioned loading.tsx)
HighlanderOP
oooo ok, thanks for that (in a meeting rn so i only glossed over your msg)
it's fine 🙂
Take a look at the loading.js and it will solve your problem mostly
Take a look at the loading.js and it will solve your problem mostly
Pharaoh Hound
If
the key thing to know about
AnotherClientComponent
is completely independent and doesn't need anything from data
, you can just use Suspense
directly. Just move the data fetching lower, add a suspense boundary :const ServerComponent = async () => {
const data = await fetch()
return <div>{...}</div>
}
export default async function Page({
params: { thing },
searchParams
}: PageProps) {
return (
<>
<Suspense fallback={<Spinner />}>
<ServerComponent />
</Suspense>
<AnotherClientComponent />
</>
)
}
the key thing to know about
loading.tsx
is it just wraps your page.tsx
in something like the above. If you do this, on initial render the user will see AnotherClientComponent
rendered and then when the fetch call succeeds, the result will be streamed in and replace your fallback with the actual component. Hope that helps! Lmk if you have any other questions.@Highlander solved?