Next.js Discord

Discord Forum

Passing server action as fetcher to useSWR

Unanswered
Birman posted this in #help-forum
Open in Discord
BirmanOP
Hey, I was wondering whether what I've been doing is correct

So I've been using useSWR like this
const {data} = useSWR([arg1, arg2], myFetcher);

... fetcher definition in separate file 
"use server"
export async function myFetcher(arg1m arg2){ 
  ... access db for example
  return db.select()....
} 

So I am using a server action instead of a url endpoint to fetch the data, it works and I get the correct things apparently, but been wondering whether it is intended and correct way

38 Replies

Server Actionsa re not meant for fetching
I guess you meant "use server" in the second piece ?
(looking for the docs, the page has moved of course...)
here
"Server Actions are designed for mutations that update server-side state; they are not recommended for data fetching. Accordingly, frameworks implementing Server Actions typically process one action at a time and do not have a way to cache the return value."
@Eric Burel I guess you meant "use server" in the second piece ?
BirmanOP
yes, I meant "use server" sorry
@Eric Burel Server Actionsa re not meant for fetching
BirmanOP
so to fetch data from my databse for example in server components I can just await the function and it will not expose any APIs to the user, correct?

and on the client components what would be intended way to do so? Create an API route and use SWR?
@Birman so to fetch data from my databse for example in server components I can just await the function and it will not expose any APIs to the user, correct? and on the client components what would be intended way to do so? Create an API route and use SWR?
American Crow
You could create an API route and use whatever client side fetching lib you prefer.
But keep in mind that should be a (very) rare usecase when it comes to GETTING data.
The way is to make a server component get (fetch) the data there and pass the data down to your client components
@American Crow You could create an API route and use whatever client side fetching lib you prefer. But keep in mind that should be a (very) rare usecase when it comes to GETTING data. The way is to make a server component get (fetch) the data there and pass the data down to your client components
BirmanOP
This is something that I did initially but it felt like prop-drilling. Also I want to re-validate some of my data without users refreshing the page and this is where useSWR looks promising to me. And I don't know how to update the data for user every 5 minutes or so
@Birman This is something that I did initially but it felt like prop-drilling. Also I want to re-validate some of my data without users refreshing the page and this is where useSWR looks promising to me. And I don't know how to update the data for user every 5 minutes or so
American Crow
Regarding the prop drilling:
Fetch data where is needed. The fechting Server component should be as close to the consuming client component as possible (at the leaf)
Don't worry about doing the same fetch call in different Server components, Nextjs will automatically memoize the fetches and make sure that only one request is made in via network.
https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#fetching-data-on-the-server-with-fetch

Hm i wanted to write something else but you changed your question i can't remember now 😄 anyways hope that still answers it
Yea you can use fetch('https://...', { next: { revalidate: 3600 } }) for the second part
@American Crow Yea you can use `fetch('https://...', { next: { revalidate: 3600 } })` for the second part
BirmanOP
Yeah, I'll try this out and see if it does what I want, so general rule is to fetch data in server components and pass them down to client components, almost always

I am moving to using redis as a cache, which will store a lot of data which will constantly be updating, I want users being on page /todos/ have a list of all todos, whenever my redis cache changes (or every 2 seconds for example) I want users to have updates visible, without the need to reload the page
And to get such data from redis/database or whatever, I should make a server action and run the server action in server component, correct? Or directly call the API in the server component
American Crow
Your sentence has get datain it
its always a server component and directly call
server actions are for mutating data
@American Crow its always a server component and directly call
BirmanOP
ok, thanks, what if I have a case where I want to get data based on user's input? So he selects a category and I want to get just this category's items. I could probably get all data in the server component and then filter based on what user chose, but this somehow feels wrong, since there could be a ton of records to filter out and a lot of user's inputs
@Birman ok, thanks, what if I have a case where I want to get data based on user's input? So he selects a category and I want to get just this category's items. I could probably get all data in the server component and then filter based on what user chose, but this somehow feels wrong, since there could be a ton of records to filter out and a lot of user's inputs
American Crow
In most cases url params ?filter="north" aka query params aka searchParams
Setting searchParams in client component "syncs" the url state back to server component which can read it using function ServerComponent({searchParams})
@American Crow In most cases url params `?filter="north"` aka query params aka `searchParams` Setting searchParams in client component "syncs" the url state back to server component which can read it using `function ServerComponent({searchParams})`
BirmanOP
that's how I had this setup already, but I was getting and passing params in client components, ok, I'll try this new approach, I really want to clean up my code and do things the intended way, thanks for clarifying things up so far, if you don't mind I might ping you again if I encounter more problems with this, thanks
@Birman Hey, I was wondering whether what I've been doing is correct So I've been using useSWR like this const {data} = useSWR([arg1, arg2], myFetcher); ... fetcher definition in separate file "use server" export async function myFetcher(arg1m arg2){ ... access db for example return db.select().... } So I am using a server action instead of a url endpoint to fetch the data, it works and I get the correct things apparently, but been wondering whether it is intended and correct way
IMO, the reason of using GET method over POST method for getting data is because the response of GET can be cached while POST cannot. Graphql also using POST method for querying data by default.
For your case, I think it doesn’t matter since you are expecting the data is changing frequently and you will need either swr or react-query to update the UI without refreshing the page with refreshInterval option. You could fetch the initial data on server component and pass it down to client component as initialData. In addition, if you don’t feel like prop drilling, react-query provides a [good way](https://tanstack.com/query/latest/docs/framework/react/guides/advanced-ssr#prefetching-and-dehydrating-data) for it
American Crow
thanks Ray
Ray is the 🐐 whatever he says is 10x more correct than whatever i am yapping
BirmanOP
because I don't think I can get data from redis or my db using "fetch"
keep in mind that, the GET endpoint is static by default, you could use route segment config to change it
@Ray keep in mind that, the GET endpoint is static by default, you could use route segment config to change it
BirmanOP
could you explain what that means? I don't think I know of this
@Birman could you explain what that means? I don't think I know of this
export const dynamic = 'force-dynamic'
or
export const revalidate = 0
in the route.ts to make it dynamic
@Ray `export const dynamic = 'force-dynamic'` or `export const revalidate = 0` in the `route.ts` to make it dynamic
BirmanOP
oh, so that means GET endpoints are "evaluated during build" or do they just have longer cache? and I have to force them to not cache and handle that by redis, or perhaps make the cache period low
American Crow
both, GET endpoints are run during build and cached by default
BirmanOP
ok, this explains and clarifies a lot of things, thanks for help guys, I'll go ahead and fix the mess I made
for fetch it's easier because it already dedupes call (memoization) but just in case the SO post also explains how it works for non http data
or value you compute on the fly
@Eric Burel to avoid prop drilling in RSCs: https://stackoverflow.com/a/75533592/5513532
BirmanOP
oh, this also looks promising for a different use case I have, thanks