警告:文本内容不匹配。服务器:“我出去了” 客户:“我出去了” div

IT技术 reactjs cookies next.js
2021-03-25 21:46:35

universal-cookie在 Next.js 项目中使用,这是在控制台中返回警告的简单代码:

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</>}
    </div>
  );
}

当“我在”然后我刷新页面时,控制台中会出现以下警告:

在此处输入图片说明

我已经到处寻找解决方案。

1个回答

Next.js在服务器上预渲染每个页面

这意味着 Next.js 会提前为每个页面生成 HTML,而不是全部由客户端 JavaScript 完成。

(...) 当浏览器加载页面时,其 JavaScript 代码会运行并使页面完全交互。(这个过程称为水合作用。)

浏览器上呈现的 HTML 与服务器上生成的不匹配,因为cook.get("key")两者都返回不同的内容。

有几个选项可以解决这个问题。


#1 将设置状态移动到 useEffect

第一个解决方案是在 a 中移动设置状态useEffect

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</>}
        </div>
    );
}

#2使用next/dynamic{ ssr: false }

作为替代解决方案,也可以通过next/dynamic使用 using动态导入 React 组件来规避该问题{ ssr: false },无论该组件在哪里使用。这可以防止组件被包含在服务器上,并且仅在客户端动态加载它。

const Home = dynamic(
    () => import('../components/Home'),
    { ssr: false }
)