#use cookies() in client component only on serverside render
1 messages · Page 1 of 1 (latest)
Hi @marble ledge. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
In Next.js, you can use the cookies() function in Server Actions, Route Handlers, and Middleware, but not directly from a page or layout. This is because HTTP does not allow setting cookies after streaming starts.
Here is an example of how you can use the cookies() function:
import { createServerComponentClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
export default () => {
cookies().getAll(); // Keep cookies in the JS execution context for Next.js build
return createServerComponentClient({ cookies });
};
You can then import and use it like this:
import supabaseServer from "./supabaseServer";
(Source: Github Issue (https://github.com/vercel/next.js/issues/56630))
However, if you want to use cookies in a client component, you should read the values in useEffect to avoid creating hydration mismatches based on reading values only available in the browser.
(Source: Github Issue (https://github.com/vercel/next.js/issues/46518))
If you are dealing with cookies set in middleware, you can use the mechanism added in this pull request (https://github.com/vercel/next.js/pull/41380) to override what Next will tell Server Components about the value of the Cookie header on the request. This will make Server Component functions like cookies() return different values, even for the same request.
(Source: Github Issue (https://github.com/vercel/next.js/issues/49442))
Please note that you can't mix server and client components in the same file due to a React restriction, not Next.js.
(Source: Github Issue (https://github.com/vercel/next.js/issues/49752))
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@marble ledge kapa.ai is still learning and improving, please let us know how it did by reacting below
Create a useScreenSize hook that would sync client and server viewport. The hook should provide correct initial server value and then handle responsiveness in the client
@echo wadi
if (typeof window === 'undefined') {
const cookieStore = cookies();
const viewport = cookieStore.get(GlobalSearchParams.VIEWPORT)?.value;
return {
isDesktop: viewport === Viewport.DESKTOP,
isTablet: viewport === Viewport.TABLET,
isMobile: viewport === Viewport.MOBILE,
};
}
Can you make this usable for clientside?
Let me check the knowledge base for you. One moment! :books:
The code you provided is checking if the window object is undefined, which is a common way to determine if the code is running on the server side or the client side. The window object is only available in the browser (client side), not in Node.js (server side).
If you want to use this code on the client side, you can use the window object directly or use a state management library like Redux or Context API to store and access the viewport information. However, you can't directly use cookies() on the client side as it's a server-side function.
Here's an example of how you can modify your code to work on the client side using the window object:
let viewport;
if (typeof window !== 'undefined') {
viewport = window.innerWidth;
}
return {
isDesktop: viewport >= 1024,
isTablet: viewport < 1024 && viewport >= 768,
isMobile: viewport < 768,
};
In this example, we're using the window.innerWidth property to determine the viewport size. The viewport sizes for desktop, tablet, and mobile are just examples, you should adjust them according to your needs.
Please note that this code should be run in a useEffect hook or after the component has been mounted to ensure that the window object is available.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@marble ledge kapa.ai is still learning and improving, please let us know how it did by reacting below
@echo wadi modify this so it would work with server & client-side
Let me check the knowledge base for you. One moment! :books:
To make your code work on both server and client side, you can use a React hook such as useEffect to handle the client-side logic. This hook runs after the component has been rendered, which means it will only run on the client side.
Here's an example of how you can modify your code:
import { useState, useEffect } from 'react';
function Component() {
const [viewport, setViewport] = useState();
// This will run on server side
if (typeof window === 'undefined') {
const cookieStore = cookies();
const viewport = cookieStore.get(GlobalSearchParams.VIEWPORT)?.value;
setViewport(viewport);
}
// This will run on client side
useEffect(() => {
if (window.innerWidth >= 1024) {
setViewport('DESKTOP');
} else if (window.innerWidth < 1024 && window.innerWidth >= 768) {
setViewport('TABLET');
} else {
setViewport('MOBILE');
}
}, []);
return {
isDesktop: viewport === 'DESKTOP',
isTablet: viewport === 'TABLET',
isMobile: viewport === 'MOBILE',
};
}
In this example, we're using the useState and useEffect hooks from React. The useState hook is used to store the viewport value, and the useEffect hook is used to update this value on the client side based on the window width.
Please note that the cookies() function is not available on the client side, so you need to make sure that this code is only run on the server side. The window object is not available on the server side, so you need to make sure that the code inside the useEffect hook is only run on the client side.
Also, the viewport sizes for desktop, tablet, and mobile are just examples, you should adjust them according to your needs.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@marble ledge kapa.ai is still learning and improving, please let us know how it did by reacting below
<@&1089670008898080870> create this as a hook
@echo wadi modify your code to be a hook and it should be able to use inside client components
Let me check the knowledge base for you. One moment! :books:
Sure, you can create a custom hook that can be used inside client components. Here's how you can modify the code:
import { useState, useEffect } from 'react';
function useViewport() {
const [viewport, setViewport] = useState();
// This will run on server side
if (typeof window === 'undefined') {
const cookieStore = cookies();
const viewport = cookieStore.get(GlobalSearchParams.VIEWPORT)?.value;
setViewport(viewport);
}
// This will run on client side
useEffect(() => {
if (window.innerWidth >= 1024) {
setViewport('DESKTOP');
} else if (window.innerWidth < 1024 && window.innerWidth >= 768) {
setViewport('TABLET');
} else {
setViewport('MOBILE');
}
}, []);
return {
isDesktop: viewport === 'DESKTOP',
isTablet: viewport === 'TABLET',
isMobile: viewport === 'MOBILE',
};
}
export default useViewport;
You can then use this hook in your client components like this:
import useViewport from './useViewport';
function MyComponent() {
const { isDesktop, isTablet, isMobile } = useViewport();
// Your component logic here
}
Please note that the cookies() function is not available on the client side, so you need to make sure that this code is only run on the server side. The window object is not available on the server side, so you need to make sure that the code inside the useEffect hook is only run on the client side.
Also, the viewport sizes for desktop, tablet, and mobile are just examples, you should adjust them according to your needs.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@marble ledge kapa.ai is still learning and improving, please let us know how it did by reacting below
@echo wadi From your example how can I make sure cookies() function is only ran on the server side?
Let me check the knowledge base for you. One moment! :books:
The cookies() function is a server-side function and it's not available on the client side. To ensure that it's only run on the server side, you can use the typeof window === 'undefined' check. This is because the window object is only available in the browser (client side), not in Node.js (server side).
Here's how you can modify the code to ensure that cookies() is only run on the server side:
import { useState, useEffect } from 'react';
function useViewport() {
const [viewport, setViewport] = useState();
// This will run on server side
if (typeof window === 'undefined') {
const cookieStore = cookies();
const viewport = cookieStore.get(GlobalSearchParams.VIEWPORT)?.value;
setViewport(viewport);
}
// This will run on client side
useEffect(() => {
if (window.innerWidth >= 1024) {
setViewport('DESKTOP');
} else if (window.innerWidth < 1024 && window.innerWidth >= 768) {
setViewport('TABLET');
} else {
setViewport('MOBILE');
}
}, []);
return {
isDesktop: viewport === 'DESKTOP',
isTablet: viewport === 'TABLET',
isMobile: viewport === 'MOBILE',
};
}
export default useViewport;
In this code, the cookies() function is inside the if (typeof window === 'undefined') block, which means it will only run if the window object is undefined, i.e., on the server side.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@marble ledge kapa.ai is still learning and improving, please let us know how it did by reacting below