Error with server side Next js 14
Answered
Californian posted this in #help-forum
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.
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>
)
}28 Replies
CalifornianOP
I have this function in actions/getTest. tsx :
And I call that in app/test (so my test page) :
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 :
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."
// 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 !
@Californian 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;
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>
)
}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 :
But now, when I npm run build I got :
Do you have any ideas ?
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
I don't really know whether it is better to be static or dynamic
@Californian 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
ok do this in the page
export const dynamic = 'force-dynamic'@Californian 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
btw, static page would be more fast than a dynamic page and also SEO friendly
CalifornianOP
export const dynamic = 'force-dynamic'
Amazin it works thank you !
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 ?
, it is dynamic no ? How should I do it static ?
@Californian with export const dynamic = 'force-dynamic'
, it is dynamic no ? How should I do it static ?
export const dynamic = 'force-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 sitedynamic 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 pageCalifornianOP
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 ?
Correct ?
CalifornianOP
Thank you very much for your help and advices, really appreciate 🙂 Have a nice day !