添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
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 }
                The easier approach for me this time was useEffect hook. Here we can find more info about why this is happening. That post helped me a lot to understand more about this weird behavior.
– Jean Manzo
                Feb 9, 2022 at 19:53
                Great answer.   Option #1: If the component is made by yourself and you can modify the state logic.  Option #2: If the component uses logic that comes from third party library and cannot be modified.
– giorgiline
                Sep 11, 2022 at 12:55
                Thanks for your answer, juliomalves. What if I'm using usehooks-ts.com/react-hook/use-local-storage, which already uses useEffect? I'm curious what you'd recommend for stackoverflow.com/q/74022328/470749 Thanks
– Ryan
                Oct 15, 2022 at 13:04
                @Ryan The problem is how the useLocalStorage hook sets its initial state - the readValue function returns different things on the server and on the client when the localStorage value you're using is set. Either you don't use useLocalStorage and write your own logic; or you dynamically import the component where it's used using next/dynamic with { ssr: false } (see my #2 solution).
– juliomalves
                Oct 15, 2022 at 13:10

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

Is that the root html element? <html suppressHydrationWarning="true"> because I'm not sure how this links to react knowing :D – Jamie Hutber Feb 27 at 21:58

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

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center. – Community Jul 29, 2022 at 18:28

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.