Next.js Discord

Discord Forum

server action being duplicated despite wrapping with react cache

Answered
netwrx posted this in #help-forum
Open in Discord
Avatar
using 15.1.
it seems to only occur when using redirect inside of a RSC

can provide more code if needed. maybe im doing this wrong

-- i understand middleware exists but i prefer validation to be at the top level.
Answered by Alfonsus Ardani
In any case, it looks like cache is doing its job correctly. It only shows once per request. The problem is (as near said), that the request is being made twice
View full answer

47 Replies

Avatar
i dont understand the context on how react's cache is being used here. Can you provide more information?
Avatar
yeah sure!
// actions.ts
const _get_session = async (): Promise<
    Session | null
> => {
    console.log("HIT at - ", new Date().toLocaleTimeString());

    const store = await cookies();
    const session_id = store.get("session");
    if (!session_id) {
        // cookie not found
        return null;
    }

    const data = await db.stuff(session_id);

    if (!data.length) {
        return null;
    }

    return session;
};

export const get_session = cache(_get_session);
Avatar
and, where are they used and what behavior did you expect them to do?
Avatar
everywhere kind of. im attempting to dedupe requests because i use the session's data on things like the layout, pages, components inside of those pages, etc.
Avatar
in a single request?
Avatar
wdym?
Avatar
you saw "HIT at - " console log being logged repeatedly in a single request?
Avatar
ah yes:

// /protected/page.tsx

import { SignInForm } from "@/app/protected/components";
import { get_session } from "@/lib/server/auth/actions";
import Link from "next/link";
import { redirect } from "next/navigation";

export default async function Page() {
    const session = await get_session();
    if (session) {
        redirect("/");
    }

    return (
        <>
            <Link href="/">go to /</Link>
            {session ? <>ur already signed in dummy</> : <SignInForm />}
        </>
    );
}


✓ Starting...
 ✓ Ready in 1740ms
 ○ Compiling / ...
 ✓ Compiled / in 2.7s
HIT at -  11:10:32 PM
 GET / 200 in 3279ms
 ✓ Compiled /favicon.ico in 206ms
 GET /favicon.ico?favicon.45db1c09.ico 200 in 392ms
 ✓ Compiled /protected in 351ms
HIT at -  11:10:36 PM
 GET /protected 200 in 641ms
HIT at -  11:10:37 PM
 GET / 200 in 271ms
HIT at -  11:10:37 PM
 GET / 200 in 271m


this is me simply going from / to /protected whilst logged in, using nextjs' Link component
Avatar
did you refresh your site at this point?
Image
Avatar
nope, that was the redirect's doings
Avatar
why is redirect redirecting to / when already at / ?
Avatar
because of the redirect in /protected
Avatar
then, did you refresh your site at this point?
Image
Avatar
no
Avatar
do you have any idea why your app could've redirected to the same route from / to /?
Avatar
this is me simply going from / to /protected whilst logged in, using nextjs' Link component
i didnt press or do anything else 😭
Avatar
try removing this Link
Image
in your protected page
delete .next folder and rerun npm dev
and see if / still gets logged twice
Avatar
same result...
Avatar
Asian black bear
On a slightly different note, you're saying you are using a server action, but _get_session is not a server action. It's just a server-side function. And judging by your logs that Alfon pointed to caching is not the problem - just that you are requesting the root page twice for some reason. cache only memoizes values during a single request.
Avatar
In any case, it looks like cache is doing its job correctly. It only shows once per request. The problem is (as near said), that the request is being made twice
Answer
Avatar
oh, never thought about in that perspective. i wonder if my browser is fucked
Avatar
well, my initial suspect is the prefetching mechanism from Link
or your middleware
Avatar
dont have any middleware
Avatar
dang
send your repo? maybe i can spot a mistake
Avatar
wow. it was absolutely my browser
Avatar
wait how :kekw:
Avatar
i spun up firefox
lmaooo wtf
✓ Starting...
 ✓ Ready in 1673ms
 ○ Compiling / ...
 ✓ Compiled / in 2.7s
HIT at -  11:20:35 PM
 GET / 200 in 3151ms
 ✓ Compiled /protected in 345ms
HIT at -  11:20:37 PM
 GET /protected 200 in 490m

this is absolutely what i expect wow
im slightly new to next.js in general. could you explain this difference please?
Avatar
Asian black bear
A server action is a function that is explicitly marked using "use server" and callable from the client.
Avatar
are there any gotchas between using a server sided function or action for my use case?
i know i could simply just create an api route to return the session for the client but
Avatar
Asian black bear
It makes no sense to use dedicated server actions from server-side code if you meant that.
Avatar
ah, which i plan to do
Avatar
Asian black bear
And since you seemingly want to check the session server-side while rendering the page you just use just regular functions.
No "use server" directives or any other magic.
Avatar
yes i dislike pending state
well thanks both
appreciate the time