Accessing document instance in client component throws error
Answered
Philippine Crocodile posted this in #help-forum
Philippine CrocodileOP
// src/hooks/cookies.tsx
"use client"
import { useState } from "react";
export const useCookies = (key: string) => {
const [c] = useState(() => {
const cookie = document.cookie.split(";").find(t => t.split('=')[0].trim() === key);
return cookie?.split('=')[1].trim()
});
return c;
}It is working completely fine but shows this error in on pages
Answered by Transvaal lion
You can use this.
Better to pass cookies from server component to client component or use library like js-cookie/cookies-next. Also can go through this discussion https://github.com/vercel/next.js/discussions/79665
'use client';
import { useSyncExternalStore } from 'react';
function readCookie(key: string): string | null {
if (typeof document === 'undefined') return null;
const cookie = document.cookie
.split(';')
.find((t) => t.split('=')[0].trim() === key);
return cookie ? decodeURIComponent(cookie.split('=')[1].trim()) : null;
}
export const useCookies = (key: string) => {
return useSyncExternalStore(
() => () => {},
() => readCookie(key),
() => null,
);
};Better to pass cookies from server component to client component or use library like js-cookie/cookies-next. Also can go through this discussion https://github.com/vercel/next.js/discussions/79665
4 Replies
Transvaal lion
Even if it is client component, nextjs will try to prerender it and document will be undefined. You should read cookies in useEffect
Philippine CrocodileOP
using
useEffect hook gives build errors, saying you might not need to use useEffectTransvaal lion
You can use this.
Better to pass cookies from server component to client component or use library like js-cookie/cookies-next. Also can go through this discussion https://github.com/vercel/next.js/discussions/79665
'use client';
import { useSyncExternalStore } from 'react';
function readCookie(key: string): string | null {
if (typeof document === 'undefined') return null;
const cookie = document.cookie
.split(';')
.find((t) => t.split('=')[0].trim() === key);
return cookie ? decodeURIComponent(cookie.split('=')[1].trim()) : null;
}
export const useCookies = (key: string) => {
return useSyncExternalStore(
() => () => {},
() => readCookie(key),
() => null,
);
};Better to pass cookies from server component to client component or use library like js-cookie/cookies-next. Also can go through this discussion https://github.com/vercel/next.js/discussions/79665
Answer
@Transvaal lion You can use this.
typescript
'use client';
import { useSyncExternalStore } from 'react';
function readCookie(key: string): string | null {
if (typeof document === 'undefined') return null;
const cookie = document.cookie
.split(';')
.find((t) => t.split('=')[0].trim() === key);
return cookie ? decodeURIComponent(cookie.split('=')[1].trim()) : null;
}
export const useCookies = (key: string) => {
return useSyncExternalStore(
() => () => {},
() => readCookie(key),
() => null,
);
};
Better to pass cookies from server component to client component or use library like js-cookie/cookies-next. Also can go through this discussion https://github.com/vercel/next.js/discussions/79665
Philippine CrocodileOP
Thanks brother, all of my old custom hooks where throwing either warnings or errors after update, now it'll be refactored