Next.js Discord

Discord Forum

Error with server side Next js 14

Answered
Californian posted this in #help-forum
Open in Discord
CalifornianOP
Hi,

I am using Next Js 14 with app router.

I have in supabase.ts
import {
createServerComponentClient,
createServerActionClient,
createRouteHandlerClient,
} from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import { cache } from 'react';
import 'server-only';

export const dynamic = 'force-dynamic';

export const getDbOnServer = cache(async () => {
const cookieStore = await cookies();
return createServerComponentClient({ cookies: () => cookieStore });
});

export const getDbOnAction = cache(async () => {
const cookieStore = await cookies();
return createServerActionClient({ cookies: () => cookieStore });
});

export const getDbOnRoute = cache(async () => {
const cookieStore = await cookies();
return createRouteHandlerClient({ cookies: () => cookieStore });
});



export async function supabaseServerComponentClient() {
return createServerComponentClient({ cookies });
}


I am using that here :

import { Escortes } from "@/types";
import { supabaseServerComponentClient } from '@/utils/supabase';

const getTest = async (): Promise<Escortes[] | null> => {
// Créez le client Supabase à l'intérieur de votre fonction asynchrone pour conserver le contexte asynchrone.
const supabaseClient = await supabaseServerComponentClient();
const { data, error } = await supabaseClient
.from('profiles')
.select('*');

if (error) {
console.error(error.message);
throw error;
}

return data || null;
};

export default getTest;


And in a server page ( I am not using "use client"), I have import getTest from '@/actions/getTest';


const fetchData = async () => {
try {
let escortesData = await getTest();
} catch (error) {
console.error('Error fetching profiles:', error);
}
};
fetchData();


And I have as error message : Error: Invariant: cookies() expects to have requestAsyncStorage, none available.
Answered by Ray
you can't call fetchData() at the top level, you should call it inside the component
// app/test/page.tsx
export default async function Page(){
   const profiles = await fetchData()

   return (
      <div>hi</div>
   )  
}
View full answer

28 Replies

@Californian Hi, I am using Next Js 14 with app router. I have in supabase.ts import { createServerComponentClient, createServerActionClient, createRouteHandlerClient, } from '@supabase/auth-helpers-nextjs'; import { cookies } from 'next/headers'; import { cache } from 'react'; import 'server-only'; export const dynamic = 'force-dynamic'; export const getDbOnServer = cache(async () => { const cookieStore = await cookies(); return createServerComponentClient({ cookies: () => cookieStore }); }); export const getDbOnAction = cache(async () => { const cookieStore = await cookies(); return createServerActionClient({ cookies: () => cookieStore }); }); export const getDbOnRoute = cache(async () => { const cookieStore = await cookies(); return createRouteHandlerClient({ cookies: () => cookieStore }); }); export async function supabaseServerComponentClient() { return createServerComponentClient({ cookies }); } I am using that here : import { Escortes } from "@/types"; import { supabaseServerComponentClient } from '@/utils/supabase'; const getTest = async (): Promise<Escortes[] | null> => { // Créez le client Supabase à l'intérieur de votre fonction asynchrone pour conserver le contexte asynchrone. const supabaseClient = await supabaseServerComponentClient(); const { data, error } = await supabaseClient .from('profiles') .select('*'); if (error) { console.error(error.message); throw error; } return data || null; }; export default getTest; And in a server page ( I am not using "use client"), I have import getTest from '@/actions/getTest'; const fetchData = async () => { try { let escortesData = await getTest(); } catch (error) { console.error('Error fetching profiles:', error); } }; fetchData(); And I have as error message : Error: Invariant: cookies() expects to have requestAsyncStorage, none available.
could you show the full code on the page
CalifornianOP
I have this function in actions/getTest. tsx :
import { supabaseServerComponentClient } from '@/utils/supabase';

const getTest = async () => {
    const supabaseClient = await supabaseServerComponentClient();
    const { data, error } = await supabaseClient
        .from('profiles')
        .select('*');

    if (error) {
        console.error(error.message);
        throw error;
    }

    return data || null;
};

export default getTest;


And I call that in app/test (so my test page) :

import getTest from '@/actions/getTest';


const fetchData = async () => {
    try {
        let profiles = await getTest();
    } catch (error) {
        console.error('Error fetching profiles:', error);
    }
};
fetchData();


const MaPage = () => {
    return (
        <div>
            Hi
        </div>
    );
};

export default MaPage;
And the supabaseServerComponent is defined here :

// utils/supabase.ts
import {
    createServerComponentClient,
    createServerActionClient,
    createRouteHandlerClient,
  } from '@supabase/auth-helpers-nextjs';
  import { cookies } from 'next/headers';
  import { cache } from 'react';
  import 'server-only';

  
  export const dynamic = 'force-dynamic';
  
  export const getDbOnServer = cache(async () => {
    const cookieStore = await cookies();
    return createServerComponentClient({ cookies: () => cookieStore });
  });
  
  export const getDbOnAction = cache(async () => {
    const cookieStore = await cookies();
    return createServerActionClient({ cookies: () => cookieStore });
  });
  
  export const getDbOnRoute = cache(async () => {
    const cookieStore = await cookies();
    return createRouteHandlerClient({ cookies: () => cookieStore });
  });
  
  export async function supabaseServerComponentClient() {
    const cookieStore = await cookies(); // Make sure this is directly in the async path
    return createServerComponentClient({ cookies: () => cookieStore });
  }


It is a simple page where I wanted to do test. When I npm run dev, it works, it displays the data.

But when I npm run build to deploy on Vercel, then I get : "Error: Invariant: cookies() expects to have requestAsyncStorage, none available."
@Ray could you show the full code on the page
CalifornianOP
If you need more code, tell me ! Thank you for your help !
Answer
@Ray you can't call `fetchData()` at the top level, you should call it inside the component ts // app/test/page.tsx export default async function Page(){ const profiles = await fetchData() return ( <div>hi</div> ) }
CalifornianOP
Thank you, here is the page I did now :

import getTest from '@/actions/getTest';

const fetchData = async () => {
    try {
        let profiles = await getTest();
    } catch (error) {
        console.error('Error fetching profiles:', error);
    }
};





export default async function Page() {

    const profiles = await fetchData()

    return (
        <div>
            Hi
        </div>
    );
};


But now, when I npm run build I got :
Generating static pages (0/23)  [=   ]Error fetching profiles: d [Error]: Dynamic server usage: Page couldn't be rendered statically because it used `cookies`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error
    at o (/home/matt/.next/server/chunks/75.js:17:30107)
    at h (/home/matt/.next/server/app/test/page.js:1:31450)
    at a (/home/matt/.next/server/app/test/page.js:1:3044)
    at l (/home/matt/.next/server/app/test/page.js:1:3453)


Do you have any ideas ?
CalifornianOP
I wanted the page to be server side rendered so that I gain performance and my SEO is better !

I don't really know whether it is better to be static or dynamic
CalifornianOP
export const dynamic = 'force-dynamic'

Amazin it works thank you !
@Ray btw, static page would be more fast than a dynamic page and also SEO friendly
CalifornianOP
So it would be better no ?
depend on your use case
CalifornianOP
with export const dynamic = 'force-dynamic'
, it is dynamic no ? How should I do it static ?
CalifornianOP
Thanks ! What do you advice me ? What is better? How can I know ?
the data won't be change on a static page unless you use revalidatePath or rebuild the site
dynamic page will always fetch the data from the data source
@Californian Thanks ! What do you advice me ? What is better? How can I know ?
so its depend on what you are building
CalifornianOP
If this is a page where data are not changed ! Like a marketplace, probably static is better, right ?
yes
static page will output a html file
CalifornianOP
Ok ! And if I want to modify data, I can use "use client", it is kind of dynamic ! Correct ?
@Californian Ok ! And if I want to modify data, I can use "use client", it is kind of dynamic ! Correct ?
yes, client side rendering or use revalidatePath to regenerate the page
CalifornianOP
Ok ! so to sum up, I use sever side with static if the data don't change, so that SEO friendly and fast. And if I have data that need to be updated while a user is on the page without rendering, then use client.

Correct ?
CalifornianOP
Thank you very much for your help and advices, really appreciate 🙂 Have a nice day !