Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I'm using
universal-cookie
in Next.js project and this the simple code that return a warning in console:
import React, { useState } from "react";
import Cookies from "universal-cookie";
import styles from "../styles/Home.module.css";
export default function Home() {
const cook = new Cookies();
const [session, setSession] = useState(cook.get("key"));
const setCookie = () => {
cook.set("key", "hola", { secure: true });
setSession(cook.get("key"));
const deleteCookie = () => {
cook.remove("key", { secure: true });
setSession(undefined);
return (
<div className={styles.container}>
<button onClick={() => setCookie()}>Save Cookie</button>
<button onClick={() => deleteCookie()}>Delete Cookie</button>
{session ? <>I'm in</> : <>I'm out</>}
When "I'M IN" and then I refresh the page the follow warning appear in console:
I have already looked everywhere for a solution.
Next.js pre-renders every page on the server.
By default, Next.js pre-renders every page. This means that Next.js generates HTML for each page in advance,
instead of having it all done by client-side JavaScript.
(...) When a
page is loaded by the browser, its JavaScript code runs and makes the
page fully interactive. (This process is called hydration.)
— Next.js, Pages, Pre-rendering
The hydration issue occurs because the HTML rendered on the browser doesn't match the one generated on the server. In your case this is because cook.get("key")
returns different things in both.
There are a couple of options to solve the issue.
#1 Moving setting state to useEffect
The first solution is to move setting the state inside a useEffect
. This forces the state to only be set on the client-side, so no mismatches will occur.
export default function Home() {
const cook = new Cookies();
const [session, setSession] = useState();
// `setCookie` and `deleteCookie` code here
useEffect(() => {
setSession(cook.get("key"));
}, []);
return (
<div className={styles.container}>
<button onClick={() => setCookie()}>Save Cookie</button>
<button onClick={() => deleteCookie()}>Delete Cookie</button>
{session ? <>I'm in</> : <>I'm out</>}
#2 Using next/dynamic
with { ssr: false }
As an alternate solution, the issue can also be circumvented by dynamically importing the React component with next/dynamic
using { ssr: false }
, wherever the component is used. This prevents the component from being included on the server, and dynamically loads it on the client-side only.
const Home = dynamic(
() => import('../components/Home'),
{ ssr: false }
–
–
–
–
using suppresshydrationwarning
attribute on the html element (which differs) worked for me.. It acts only at single level as per documentation below:
https://reactjs.org/docs/dom-elements.html#suppresshydrationwarning
–
in my case, when I turned my reactStrictMode
to false
in my next.config.js file, this Warning occurred.
then I had to turn it back to true
and after that, the Warning disappeared
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.