Next.js Discord

Discord Forum

server action being duplicated despite wrapping with react cache

Answered
netwrx posted this in #help-forum
Open in Discord
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
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

i dont understand the context on how react's cache is being used here. Can you provide more information?
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);
and, where are they used and what behavior did you expect them to do?
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.
in a single request?
wdym?
you saw "HIT at - " console log being logged repeatedly in a single request?
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
did you refresh your site at this point?
nope, that was the redirect's doings
why is redirect redirecting to / when already at / ?
because of the redirect in /protected
then, did you refresh your site at this point?
no
do you have any idea why your app could've redirected to the same route from / to /?
this is me simply going from / to /protected whilst logged in, using nextjs' Link component
i didnt press or do anything else 😭
try removing this Link
in your protected page
delete .next folder and rerun npm dev
and see if / still gets logged twice
same result...
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.
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
oh, never thought about in that perspective. i wonder if my browser is fucked
well, my initial suspect is the prefetching mechanism from Link
or your middleware
dont have any middleware
dang
send your repo? maybe i can spot a mistake
wow. it was absolutely my browser
wait how :kekw:
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
Asian black bear
A server action is a function that is explicitly marked using "use server" and callable from the client.
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
Asian black bear
It makes no sense to use dedicated server actions from server-side code if you meant that.
ah, which i plan to do
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.
yes i dislike pending state
well thanks both
appreciate the time