Unwanted flash/loading state when using searchParams in page to fetch data in a server component
Answered
Persian posted this in #help-forum
PersianOP
I'm not sure how to do this "the nextjs way" after upgrading to nextjs 16. Basically I have two searchParams "from" and "to" that needs to be passed in as props to multiple server components that will fetch some data server side.
and
Then inside HomeContainer I have this:
Where
When I refresh the page (production build on Vercel) it blinks.. I thought I would be partially static and/or prerendered when doing it like this?
What is the correct way to solve this?
Thanks.
export type SearchParams = {
from?: string;
to?: string;
};and
page.tsxexport default async function Home(props: {
searchParams?: Promise<SearchParams>;
}) {
const searchParams = props.searchParams?.then((sp) => ({
from: sp.from,
to: sp.to,
}));
return (
<Suspense>
<HomeContainer searchParams={searchParams} />
</Suspense>
);
}Then inside HomeContainer I have this:
export async function HomeContainer({ searchParams }: HomeProps) {
const params = await searchParams;
[...]
<Suspense key={`componentA-${params?.from}-${params?.to}`}>
<ComponentA from={params?.from} to={params?.to} />
</Suspense>
More similar components below that fetches data based on `from` and `to`Where
ComponentA is like this:export const ComponentA = async ({ from, to }: Props) => {
const data = doSomeFetching(from, to);
[...]`When I refresh the page (production build on Vercel) it blinks.. I thought I would be partially static and/or prerendered when doing it like this?
What is the correct way to solve this?
Thanks.
8 Replies
@Persian I'm not sure how to do this "the nextjs way" after upgrading to nextjs 16. Basically I have two searchParams "from" and "to" that needs to be passed in as props to multiple server components that will fetch some data server side.
export type SearchParams = {
from?: string;
to?: string;
};
and `page.tsx`
export default async function Home(props: {
searchParams?: Promise<SearchParams>;
}) {
const searchParams = props.searchParams?.then((sp) => ({
from: sp.from,
to: sp.to,
}));
return (
<Suspense>
<HomeContainer searchParams={searchParams} />
</Suspense>
);
}
Then inside HomeContainer I have this:
export async function HomeContainer({ searchParams }: HomeProps) {
const params = await searchParams;
[...]
<Suspense key={`componentA-${params?.from}-${params?.to}`}>
<ComponentA from={params?.from} to={params?.to} />
</Suspense>
More similar components below that fetches data based on `from` and `to`
Where `ComponentA` is like this:
export const ComponentA = async ({ from, to }: Props) => {
const data = doSomeFetching(from, to);
[...]
`
When I refresh the page (production build on Vercel) it blinks.. I thought I would be partially static and/or prerendered when doing it like this?
What is the correct way to solve this?
Thanks.
" I thought I would be partially static and/or prerendered when doing it like this?"
it is partially static. you have a static shell component (Home) and the rest is dynamic
it is partially static. you have a static shell component (Home) and the rest is dynamic
try moving the
await searchparams in ComponentAAnswer
PersianOP
Thanks! I’ll try to reorganize
PersianOP
I’ve turned on the cacheComponents, so I guess it’s those warnings that confuses me when using await.
yeah
@Persian I’ve turned on the cacheComponents, so I guess it’s those warnings that confuses me when using await.
hey how is it going with cachedComponents? did you manage to solve it?
PersianOP
Hey! Yes, i managed to solve it, however i've been experiencing more layout shift with 16 than 15 due to how cacheComponents and await work. Guess I just need to get used to how it works. My only "issue" now is that since i'm using query params, and I'd like to fetch data depending on those query params in a component quite deep in the react tree I need to pass that Promise<searchParams> in multiple components. Thanks for your help!
PersianOP
And to add to my list of "complaints": Since i'm awaiting the query params quite deep, I need a suspense of course around that component. But then that Suspense won't react to changes to searchParams as I need a
key prop on that Suspense. The best key would have been the searchParams.. but they don't get resolved in that given component as I'd like to resolve that as deep as possible... This just seems a bit off. Not sure if i'm doing something wrong here or not.