I have been working with React Server Components and Server Actions in Next.js for the last 6 months. While I am excited about Server Components and their ability to execute code on the server, I am not convinced (yet) by the story of data fetching in Client Components (without Server Actions).
Since I have seen the question (âCan I fetch data with Server Actions?â) coming up several times among developers on different occasions, I want to share a few insights here.
In a React Server Component, data fetching is straightforward. Since these components allow you to execute code on the server, you can directly access the data layer (e.g. database) from the UI:
The getPosts function here just mimics a database query with an artificial delay. In the end getPosts could also implement a request to a third-party API or some other data source:
You can also extend the previous Server Component with a Suspense boundary to enable streaming and a loading state. This way the user can see the each piece of content as soon as it is available and gets a loading indicator in the meantime for the remaining content:
But what about the data fetching story in Client Components? Most often someone would just recommend you to just fetch data in Server Components and to pass it down to Client Components. And usually thatâs the best advice.
But there are cases where you want to fetch data in Client Components. For instance, when you want to fetch data on a button click (e.g. âLoad Moreâ) or scroll event (e.g. infinite scroll). There you can surely pass down the initial subset of data from the Server Component to the Client Component, but you might want to fetch more data in the Client Component eventually.
The official recommendation by Next.js is to use Route Handlers for data fetching in Client Components, because Route Handlers allow you to implement an API in your Next.js application. For example, in a app/api/posts/route.ts file you could implement a Route Handler to fetch posts via a GET request:
Then you can fetch the data in your Client Component with a fetch request. We are using the most popular data fetching library react-query and omit its setup for the sake of keeping things simple here. The following only shows how to fetch the data in a Client Component:
For end users this implementation with a Client Component will feel identical to the Server Component implementation, because they will see a loading indicator until the data is fetched and then the posts will be displayed.
There are two downsides to this approach:
Letâs check out how this may work with Server Actions.
The official Next.js documentation says that Server Actions are only for writing (mutating) and not for reading (querying) data. But letâs do it nevertheless for fetching data in a Client Component with Server Actions for the sake of having this argument:
The user experience (UX) will be the same as with the Route Handler. But the developer experience (DX) is improved here:
First, we can reuse the getPosts function from the Server Component in the Client Component. We donât have to implement a Route Handler and we donât have to call this route handler with a HTTP fetch request. From a DX perspective we are performing a typed remote procedure call (RPC) and not an untyped HTTP request.
And second, the returned data from getPosts is type safe out of the box, because we are just calling a typed function here and no loosely typed API endpoint.
The only thing that we would have to change is marking the previous getPosts function as a Server Action, if it really accesses server-side resources (e.g. database):
And to be honest, this is how I did it over the last months.
Strategy: I started out by implementing query functions decoupled (meaning: /queries/get-posts.ts ) from my Server Components. Whenever I had to reuse these query functions in Client Components, I just marked them as Server Actions and moved the file from the /queries folder to a /actions folder, i.e. /actions/get-posts.ts .
Benefits in a nutshell: This way I didnât have to implement a Route Handler, was able to reuse the query function in my Client Component, and would have a typed data fetching experience as a developer.
But I know that this is not the official recommendation. Data fetching with Server Actions comes with drawbacks too:
So far I did not have any problems with these restrictions, because using a Server Action for data fetching in a Client Component only happens occasionally. However, I am curious to see how the official recommendation will evolve in the future.
But I know that this is not the end of the story. There is a reason why the React and Next teams are not recommending Server Actions for data fetching. In the future there will be better ways to fetch data in Client Components, they are just not here yet.
For example, I certainly know that Reactâs use will be the next game changer for data fetching in Client Components. Perhaps this gets followed by Async Client Components . And who knows how we will be using client-side data fetching like React Query in the future.
However, we are not there (yet) and personally I find the current data fetching story in Client Components (without Server Actions) not as compelling as the one in Server Components or the one in Client Components with Server Actions. Whatâs your take on this topic? Feel free to join the discussion!
You can find the repository for this tutorial over here . If you want to go beyond this, check out âThe Road to Nextâ and get on the waitlist!