Fetch on Server for Client Component
Unanswered
New Guinea Freshwater Crocodile posted this in #help-forum
New Guinea Freshwater CrocodileOP
Hey guys I am not a newbie, but still I am struggling to understand how to fetch data on the server for client components properly.
Currently I wrap my client components with server components where I fetch data and pass the result by props. This works fine, the problem is it will work only if my server component is direct child of another server component right? But this is quite limiting. I am writing a heavily animated front page with motion (ex framer motion). That said, almost all components if not entire page must be client components for better orchestration. However my data does not change over render. So there's no point to introduce tanstack query or similar to fetch data on every page load, not even talking about that this async process would cause extra rerender that I will have to handle. The content should be simply fetched on the server once and if I need to update the page I will call my revalidation endpoint.
My question is then. Is there a way how to fetch data on the server in the middle of the client components tree?
Currently I wrap my client components with server components where I fetch data and pass the result by props. This works fine, the problem is it will work only if my server component is direct child of another server component right? But this is quite limiting. I am writing a heavily animated front page with motion (ex framer motion). That said, almost all components if not entire page must be client components for better orchestration. However my data does not change over render. So there's no point to introduce tanstack query or similar to fetch data on every page load, not even talking about that this async process would cause extra rerender that I will have to handle. The content should be simply fetched on the server once and if I need to update the page I will call my revalidation endpoint.
My question is then. Is there a way how to fetch data on the server in the middle of the client components tree?
10 Replies
New Guinea Freshwater CrocodileOP
Possible scenario how to fix that is to create a page.tsx to fetch all the data, then pass it to client wrapper where I would create a context for all nested components, that would essentially prevent massive prop drilling. However I would still prefer to know if there's better way then this.
Peterbald
You can call a server action from the client component, or you can use API routes to fetch data.
either should work fine.
New Guinea Freshwater CrocodileOP
yeah, I thought about server actions as well, thanks for that. So my subsequent question is, does it violate something? Next is mentioning usage of server actions mainly for forms.
However Server Actions or calling Api route require a round trip to the server, right? The only benefit with server action is I don't have to introduce an extra library to my stack.
However Server Actions or calling Api route require a round trip to the server, right? The only benefit with server action is I don't have to introduce an extra library to my stack.
Yea you should not use Server Actions (according to Next.js) for fetching data, they’re made for mutations since they perform a POST method. That said I’ve seen educators and people very deep in the React/Next.js ecosystem using (and sharing their reasons for doing so) Server Actions for data Fetching instead of spinning up a Route Handler and call it via fetch API from the client.
I believe this is Next.js’ fault because they won’t give us the “Server Function” primitive that’s React’s proposal to run code on the server, instead Next.js shipped a wrapper around “Server Functions” with the name of “Server Actions” meant to only be used for mutations… I believe we should be able to call “Server Functions” instead of “Server Actions” and we should decide if we want them to be Queries or Mutations (this is gracefully handled by Tanstack Start framework by using the Server Functions primitive instead and letting the Developer decide it’s final use)
Example: https://www.robinwieruch.de/next-server-actions-fetch-data/
I believe this is Next.js’ fault because they won’t give us the “Server Function” primitive that’s React’s proposal to run code on the server, instead Next.js shipped a wrapper around “Server Functions” with the name of “Server Actions” meant to only be used for mutations… I believe we should be able to call “Server Functions” instead of “Server Actions” and we should decide if we want them to be Queries or Mutations (this is gracefully handled by Tanstack Start framework by using the Server Functions primitive instead and letting the Developer decide it’s final use)
Example: https://www.robinwieruch.de/next-server-actions-fetch-data/
New Guinea Freshwater CrocodileOP
thanks Luis for very interesting reading. I came along to 'use' already twice today, which is enough to start exploring this functionality. Until then I assume I have not much choice then just stick with a server components wrappers, which is fine, just annoying.
@New Guinea Freshwater Crocodile thanks Luis for very interesting reading. I came along to 'use' already twice today, which is enough to start exploring this functionality. Until then I assume I have not much choice then just stick with a server components wrappers, which is fine, just annoying.
Yes the use(promise) hook is very interesting, it’s basically a way to unwrap a promise result but you still effectively need an async function that runs on the server of what you want is to run on the server.
The problem will be the same, except react now gives us a primitive to handle async stuff
The problem will be the same, except react now gives us a primitive to handle async stuff
New Guinea Freshwater CrocodileOP
well in react doc is a mention that you would want to use 'use' instead of useContext, so I believe when you fetch all required data on top level component, e.g. page, then you would be able to access the data without a heavy prop drilling, which is already more acceptable solution.
Yes, the use of “use(Context)” is basically the same as using “useContext(Context)”. The only difference is that you can conditionally call this “use” hook, unlike regular React hooks which need to be called at the top level.
Regarding to my message from earlier (about the use hook) I meant it in the use case of implementing “use(promise)” as a way to unwrap the result of a promise. It can be seen as a React version of await, in the sense that it can only be implemented inside React functions (React components and Hooks), and it also suspends the execution of the function until the promise has been resolved and the value is unwrapped.
Anyway, whatever approach you take I don’t think it’ll be a big deal as long as you’re placing <Suspense> boundaries and you avoid waterfalls.
Regarding to my message from earlier (about the use hook) I meant it in the use case of implementing “use(promise)” as a way to unwrap the result of a promise. It can be seen as a React version of await, in the sense that it can only be implemented inside React functions (React components and Hooks), and it also suspends the execution of the function until the promise has been resolved and the value is unwrapped.
Anyway, whatever approach you take I don’t think it’ll be a big deal as long as you’re placing <Suspense> boundaries and you avoid waterfalls.
New Guinea Freshwater CrocodileOP
alright, thanks for that Luis, that was a very useful chat 💪