'Cookies can only be modified in a Server Action or Route Handler'
Unanswered
American black bear posted this in #help-forum
American black bearOP
Hey everyone, I have this server action:
and I am calling it in here:
why is that happening if I am executing
'use server';
import {cookies} from 'next/headers';
import {redirect} from 'next/navigation';
import {getPosts} from '@/data/queries/posts';
import {PinoLogger} from '@/shared/lib/logger';
const logger = new PinoLogger();
export async function getPost(slug: string) {
try {
const posts = await getPosts({latest: false});
const post = posts?.posts?.data?.find(
(item) => item?.post?.slug === slug
);
if (!post) redirect('/');
cookies().set('currentPost', post.id, {path: '/'});
return post;
} catch (err) {
logger.error({
message: '[Posts page] Failed to fetch posts',
error: {
message: err.message,
stack: err.stack,
},
});
}
} and I am calling it in here:
export default async function Page({params}: Props) {
const {slug} = params;
const post = await getPost(slug);why is that happening if I am executing
cookies().set() inside a server action?53 Replies
@American black bear Hey everyone, I have this server action:
'use server';
import {cookies} from 'next/headers';
import {redirect} from 'next/navigation';
import {getPosts} from '@/data/queries/posts';
import {PinoLogger} from '@/shared/lib/logger';
const logger = new PinoLogger();
export async function getPost(slug: string) {
try {
const posts = await getPosts({latest: false});
const post = posts?.posts?.data?.find(
(item) => item?.post?.slug === slug
);
if (!post) redirect('/');
cookies().set('currentPost', post.id, {path: '/'});
return post;
} catch (err) {
logger.error({
message: '[Posts page] Failed to fetch posts',
error: {
message: err.message,
stack: err.stack,
},
});
}
}
and I am calling it in here:
export default async function Page({params}: Props) {
const {slug} = params;
const post = await getPost(slug);
why is that happening if I am executing `cookies().set()` inside a server action?
the function is not called as a server action, it's called as a regular async function because you're running it inside a server component
@iyxan23 the function is not called as a server action, it's called as a regular async function because you're running it inside a server component
American black bearOP
but can I use server actions to fetch data or just for actions (as the name says xD)?
i wouldn't recommend server actions to fetch data, it's meant for "actions" as it name implies
if you took a look at how it works, it's actually just a POST request wrapped as a nice async function, with a POST handler on the other side
yes you could fetch data with it, but i definitely would not recommend using that pattern
American black bearOP
so maybe should I change and start using route handler?
@iyxan23 i wouldn't recommend server actions to fetch data, it's meant for "actions" as it name implies
I think so, however lots of people are using server actions for data fetching
American black bearOP
but can I use apollo client insde router handlers?
client.query(query...)
i don't really know much about apollo, but generally anything should work just fine
oh you're trying to run a graphql client on route handlers?
@James4u I think so, however lots of people are using server actions for data fetching
American black bearOP
yeah, I just realized that the Next.js docs don't recommend doing this, so I asked if I really should use server actions for data fetching
@iyxan23 i don't really know much about apollo, but generally anything should work just fine
American black bearOP
but I am using graphql
what do you recommend then?
that shouldn't be an issue
not sure, im not the kind of person you'd want to ask graphql related questions to, sorry x)
American black bearOP
that's ok, it's just want to understand
thanks a lot mate
@American black bear so maybe should I change and start using route handler?
technically server actions are the same as api routes in app routers as far as I knwo
@James4u technically server actions are the same as api routes in app routers as far as I knwo
American black bearOP
so you don't recommend using api routes for data fetching either?
so you want to set cookie after data fetching?
American black bearOP
yes
with the id of the post
@American black bear so you don't recommend using api routes for data fetching either?
exactly, you shouldn't call your api routes to fetch data
American black bearOP
but as far as I know I can only set cookies inside api routes or server actions...
what should I do then?
yeah, but as we fetch data directly inside the server component
btw what's the purpose of setting cookie?
American black bearOP
I need to share the id of the post with the client components
I have small components using client side because of the user interaction and also zustand to share state across the application to prevent prop drilling
so I need to know what the current post is to make some specific stuff inside the page
but the only way of sharing this info with the client and server is using cookies
why don't you just pass the id to the client component from the server component? 🤔
@James4u why don't you just pass the id to the client component from the server component? 🤔
American black bearOP
actually yeah you are right
yeah, and if you dont' want props drilling, use context or redux for it
American black bearOP
yup I'm using zustand
great! give it a try and let me know if it works
American black bearOP
alright
thanks
sure, and don't forget to mark solution if it works 😉
@James4u sure, and don't forget to mark solution if it works 😉
American black bearOP
sorry for delay
I did this
however there's a delay of 6 seconds (which is weird)
how long was it before?
American black bearOP
before it was just the fetch, so it was like ms
here's what I'm doing
then I send this post that I found to the client component using props, as you mentioned
In the client component I added a
useEffect with the post as a dependencywhen the post is available, I set it in the store
i checked and there are only milliseconds in the server-side request, the rest of the delay is in the transition of sending the post to the client, where the client waits in the useEffect and sets the post in the store
I mean, it doesn't make any sense to take so long
Child component (the client component that receives the post as a prop):
generateData is coming from the zustand store
useEffect(() => {
if (post) {
generateData(post);
}
}, [post]);generateData is coming from the zustand store