Next.js Discord

Discord Forum

`Server Action` function not being recognised.

Answered
du_cki posted this in #help-forum
Open in Discord
Avatar
I have a function that just does
import { cookies } from "next/headers";

export async function logoutUser() {
  cookies().delete(COOKIE_NAME);
}
and its in a file that has "use server"; on top of the file.

But when I call the function from a Server Component it gives me an error;
 ⨯ Error: Cookies can only be modified in a Server Action or Route Handler. Read more: https://nextjs.org/docs/app/api-reference/functions/cookies#cookiessetname-value-options
    at logoutUser (./utils/database/auth.ts:68:67)
    at Home (./app/page.tsx:23:75)
    at stringify (<anonymous>)


Fwiw, I have other functions in this file that is also being exported as a server action and they seem to work for the most part. It's just this function that's causing me problems.
Answered by Pearls
Again, reason being that the useEffect hook can only be executed on the clientside
View full answer

28 Replies

Avatar
we'll im not sure if im fully correct but if you are calling a server action from a server component the cookies wont exist, there is a possibility that this causes the error.

maybe make sure that logoutUser is called from the client. this could be done in multiple ways.

if (typeof window !== "undefined") {
    // Code to execute on the client side
}


useEffect(() => {
    // Code to execute on the client side
}, []);


NOTE: im not fully sure that this fixes your problem, but its worth a try.
Avatar
errr, I'll try to switch it over to a client component then
Erm is there no other way to mutate the cookies inside server actions?
This throws a wrench in my current design
Avatar
Im really not sure, but ill look into it.
Avatar
Velvet ant
how do you use the logoutUser function in the Home page ?
Avatar
It's just being used like this inside a server component
export default async function Home() {
  const isLoggedOut = verifyJWTCookieAuth();

  if (!isLoggedOut) {
    await logoutUser();
    return <Login />;
  }

  redirect("/dashboard");
}
Avatar
Well you can, but the server action has to be executed from the client for it to work (since when the client executes it the clients cookies basicly gets send to the server action as context)
Avatar
But according to a github issue I skimmed through, apparently I can't mutate (.set()/.delete()) but only can .get() them on server actions which is really a bummer.
Avatar
Velvet ant
server action can only be invoked in a form or event handler and useEffect
Avatar
that doesnt make sense does it?

if i had a component like it would work? (it would prob create an infinite loop tho):
"use client"

export default function TestComponent() {
    logoutUser();

    return (<></>);
}
Avatar
Velvet ant
I guess something like this can be done:

'use client'
 
import { logoutUser } from './actions'
import { useEffect } from 'react'
 
export function Test() {
  useEffect(() => {
    updateViews();
  }, [])
 
  return null;
}


I would use it in the <Login /> component directly

or maybe the actual case can be resolved in the middleware
Avatar
Yeah so basicly just this.
Avatar
Oh lol
I see and understand the issue, the function I'm calling is being called as a server component instead of a server action which is causing the problems, useEffect does solve this issue.
Thanks y'all, I spent an hour on this mess lol.
Actually true, I'm just gonna put this in a middleware and not look back xd
Avatar
Yes, its because useEffect waits for the client to have loaded javascript, only then it will execute all the code inside the useEffect (so basicly by using useEffect you are making sure that the code inside it will be executed by the client)
Theres a small problem there i think, ofcourse you can try but the middleware is not a part of the client, i think its ran on the server so useEffect will not be available there.
Avatar
Velvet ant
cookie can be deleted in the middleware
Avatar
Yes that is true, but @du_cki wants to put the useEffect example inside of the middleware (which is not possible, it will cause an error)
Avatar
Again, reason being that the useEffect hook can only be executed on the clientside
Answer
Avatar
Yeah makes a whole lot sense now, lol thanks for the help.
Avatar
All good! Good luck, i hope everything works out.
Avatar
Thank you.