Nest.js 14 Server Components and Search Params
Unanswered
Ocicat posted this in #help-forum
OcicatOP
Hi everyone. This is my first time dealing with server components and the app router.
I have a page.tsx file which corresponds to a URL and is a server component. Fetching data from the database is straightforward.
A child component of this page.tsx includes a search bar that changes the URL via the searchParams.
Predictably, if I try to filter the results from the database while keeping it a server component, it becomes sluggish. Any change to searchParams in the URL will trigger a re-render and a new call to the database. I realize I can debounce and throttle, but I’d like to solve the problem more systematically.
Is it a good solution to fetch data from the database in a server component (layout.tsx), a parent of this page.tsx, and do the filtering in the page.tsx itself? This way, any new searchParams won’t trigger a re-render. If not, is there an alternative performant and structural solution to keeping this as a server component with state in the URL?
Thanks in advance!
I have a page.tsx file which corresponds to a URL and is a server component. Fetching data from the database is straightforward.
A child component of this page.tsx includes a search bar that changes the URL via the searchParams.
Predictably, if I try to filter the results from the database while keeping it a server component, it becomes sluggish. Any change to searchParams in the URL will trigger a re-render and a new call to the database. I realize I can debounce and throttle, but I’d like to solve the problem more systematically.
Is it a good solution to fetch data from the database in a server component (layout.tsx), a parent of this page.tsx, and do the filtering in the page.tsx itself? This way, any new searchParams won’t trigger a re-render. If not, is there an alternative performant and structural solution to keeping this as a server component with state in the URL?
Thanks in advance!
15 Replies
Dwarf Crocodile
https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#using-the-native-history-api
You can use the native history API to replace the current url without reloading the page
You can use the native history API to replace the current url without reloading the page
OcicatOP
Hi @keii , but that’s the thing. The URL must act like state in that it must cause a re-render. That’s because the search parameters will be used to filter the results from the database, which in turn, will mean a different list being rendered.
What I don’t want is a call to the database for every keystroke,
What I don’t want is a call to the database for every keystroke,
Dwarf Crocodile
Well then you could just make a small form and do a
onSubmit so each time the user presses enter or something like a Search button it will rerenderThen it would only rerender when the user wishes it to
OcicatOP
@keil , That's not the UX I want. I want the results being filtered in real time as the typing occurs.
I guess my question is this how would you make it so - keeping it all server side - that changes to searchParams do trigger re-renders but the data fecthing happens only once, when the page loads?
I guess my question is this how would you make it so - keeping it all server side - that changes to searchParams do trigger re-renders but the data fecthing happens only once, when the page loads?
Dwarf Crocodile
I dont understand what you want really. Do you have all the data and then you want to filter it or do you search the database with the searchparams?
OcicatOP
@keil , The data in question is of very moderate size, and quite static , in the sense it will only change very infrequently.
1. I want the call to the database to happen once and that's it.
2. I want the user to be able to type in the search bar and for the results from databse to be filtered in eal time, locally, without any additional calls to teh databse.
3. All of this must be kept setver side
1. I want the call to the database to happen once and that's it.
2. I want the user to be able to type in the search bar and for the results from databse to be filtered in eal time, locally, without any additional calls to teh databse.
3. All of this must be kept setver side
Dwarf Crocodile
I dont understand why you want to do this all serverside. This is textbook clientside behavior
OcicatOP
I've done this client side before. And since the data fetching is so easy server side I was going to challenge myself and keep it strictly server side.
Of course I can always create an API route, do a GET within a useEffect({},[]) and keep it client side.
You don't think doing the data eftching in layout.tsx and the filtering in a child page.tsx, all server side, would work?
Of course I can always create an API route, do a GET within a useEffect({},[]) and keep it client side.
You don't think doing the data eftching in layout.tsx and the filtering in a child page.tsx, all server side, would work?
Dwarf Crocodile
No but you can do the datafetching in a server page and then pass that data as a prop to a client component thus keeping all data fetching on server while doing all the nice clientside stuff on the client like your searching.
OcicatOP
I thought about that. My take was that changing the searchParams would still trigger a re-fecthing if the fetching was done in a server component corresponfing to the URL
Dwarf Crocodile
You can just do something like this
export default async function Page() {
const data = await getData();
return (
<ClientComponent data={data} />
)
}"use client"
export const ClientComponent = ({data}) => {
return (
<div>
{JSON.stringify(data)}
</div>
}
}@Ocicat I thought about that. My take was that changing the searchParams would still trigger a re-fecthing if the fetching was done in a server component corresponfing to the URL
Dwarf Crocodile
No, thats where you can use something like this https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#using-the-native-history-api where the updating of the searchparams doesnt trigger a reload thus not refetching the data as for my example, the
const data = await getData()OcicatOP
Great! Thank you very much for your guidance. You have been most graciopus!
Dwarf Crocodile
np