Server action works fine in static mode, fails in client-side mode.
Answered
Barbary Lion posted this in #help-forum

Barbary LionOP
Hi folks! Thanks in advance for the help.
For starters, I'm on latest (
I have a component that is part of a site builder. It uses both a client-side and a server-side mode (the former is when editing the site, the latter after the site has been published). The server action that I have written works beautifully when in publish mode, and I can see that it has been called from my console. I call the server action through hydration when published.
Unfortunately, the server action is called client-side for some reason when in edit mode (and running in a client component). I can see the direct call in the network tab, and it causes a CORS issue in this case, because the component is allowing a user to specify a URL for RSS feeds to show on their built site. I want that code to be executed server-side so I don't have to open up the site to arbitrary URLs for requests.
When editing, I call the server action through a
The code for the useEffect is below.
Any ideas on this one? I've been banging my head on it for several hours.
For starters, I'm on latest (
15.2.4
)I have a component that is part of a site builder. It uses both a client-side and a server-side mode (the former is when editing the site, the latter after the site has been published). The server action that I have written works beautifully when in publish mode, and I can see that it has been called from my console. I call the server action through hydration when published.
Unfortunately, the server action is called client-side for some reason when in edit mode (and running in a client component). I can see the direct call in the network tab, and it causes a CORS issue in this case, because the component is allowing a user to specify a URL for RSS feeds to show on their built site. I want that code to be executed server-side so I don't have to open up the site to arbitrary URLs for requests.
When editing, I call the server action through a
useEffect
hook, which from what I understand, is supported in Next JS for client components.The code for the useEffect is below.
use server
is at the top of the file that I import for getFeedContent
(app/actions/content.ts
). The return value is serializable, because it's functioning just fine when in publish mode (editing
is false).Any ideas on this one? I've been banging my head on it for several hours.
useEffect(() => {
if (editing) {
setIsLoading(true);
const fetchData = async () => {
try {
const result = await getFeedContent(toGetFeedContentInput(input));
setFeedData(result);
} catch (error) {
console.error("Error calling server action:", error);
} finally {
setIsLoading(false);
}
};
fetchData();
}
}, [debouncedInput, editing]);
Answered by LuisLl
When server actions are called outside of an “action” context (useActionState, action prop or formAction) you need to wrap them in a transition. Also with this you’ll remove the manual
That said, you should not use server actions to fetch data, they’re not meant for that and cause issues when they’re triggered multiple times since they run sequentially not in parallel, and frameworks seem not to support multiple server actions running at the same time
isLoading
flag since transition track it for you. That said, you should not use server actions to fetch data, they’re not meant for that and cause issues when they’re triggered multiple times since they run sequentially not in parallel, and frameworks seem not to support multiple server actions running at the same time
7 Replies

When server actions are called outside of an “action” context (useActionState, action prop or formAction) you need to wrap them in a transition. Also with this you’ll remove the manual
That said, you should not use server actions to fetch data, they’re not meant for that and cause issues when they’re triggered multiple times since they run sequentially not in parallel, and frameworks seem not to support multiple server actions running at the same time
isLoading
flag since transition track it for you. That said, you should not use server actions to fetch data, they’re not meant for that and cause issues when they’re triggered multiple times since they run sequentially not in parallel, and frameworks seem not to support multiple server actions running at the same time
Answer

Is the main issue that your server action is running on the client, and not on the server?

Barbary LionOP
Hey there. Thanks for the reply.
I see. That's a bit disappointing, as I was hoping to use Server actions to effectively eliminate the need for an API layer (semantically) altogether. I saw a couple of fetch examples in the docs, and I missed that it wasn't recommended. Thanks for the context. I suppose I'll look at tRPC as my potential communication layer.
You're correct, though - the main issue is that the server action was running on the client and not on the server. That said, given your info, I think it's a bit of a moot point unless there's some new development in the future that allows parallelization.
I see. That's a bit disappointing, as I was hoping to use Server actions to effectively eliminate the need for an API layer (semantically) altogether. I saw a couple of fetch examples in the docs, and I missed that it wasn't recommended. Thanks for the context. I suppose I'll look at tRPC as my potential communication layer.
You're correct, though - the main issue is that the server action was running on the client and not on the server. That said, given your info, I think it's a bit of a moot point unless there's some new development in the future that allows parallelization.

Hopefully the next.js team comes with a RPC way to do data fetching, just like Server Actions for mutations. The DX is pretty good!

Barbary LionOP
Indeed. Much appreciated for the help!

Of course, was the main issue solved?

Barbary LionOP
Ah, right. Marking the answer. Apologies. I ended up rolling tRPC. I'll mark yours as the answer.