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

and*_*nez 66 cookies reactjs next.js

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>
  );
}
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

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

jul*_*ves 125

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

\n
\n

默认情况下,Next.js预渲染每个页面。这意味着 Next.js 提前为每个页面生成 HTML,\n而不是全部由客户端 JavaScript 完成。\n预渲染可以带来更好的性能和 SEO。

\n

(...) 当浏览器加载页面时,其 JavaScript 代码会运行并使页面完全交互(此过程在 React 中称为水化)。

\n

\xe2\x80\x94 Next.js,构建您的应用程序,渲染

\n
\n

出现水合作用问题的原因是浏览器上呈现的 HTML 与服务器上生成的 HTML 不匹配。在你的情况下,这是因为cook.get("key")两者返回不同的东西。

\n

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

\n
\n

#1 将设置状态移至useEffect

\n

第一个解决方案是将状态设置移动到useEffect. 这会强制仅在客户端设置状态,因此不会发生不匹配。

\n
export default function Home() {\n    const cook = new Cookies();\n    const [session, setSession] = useState();\n    \n    // `setCookie` and `deleteCookie` code here\n\n    useEffect(() => {\n        setSession(cook.get("key"));\n    }, []);\n\n    return (\n        <div className={styles.container}>\n            <button onClick={() => setCookie()}>Save Cookie</button>\n            <button onClick={() => deleteCookie()}>Delete Cookie</button>\n            {session ? <>I\'m in</> : <>I\'m out</>}\n        </div>\n    );\n}\n
Run Code Online (Sandbox Code Playgroud)\n
\n

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

\n

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

\n
const Home = dynamic(\n    () => import(\'../components/Home\'),\n    { ssr: false }\n)\n
Run Code Online (Sandbox Code Playgroud)\n

  • 很好的答案。选项#1:如果组件是您自己制作的,您可以修改状态逻辑。选项#2:如果组件使用来自第三方库的逻辑且无法修改。 (3认同)
  • 这次对我来说更简单的方法是“useEffect”钩子。在这里我们可以找到有关[为什么会发生这种情况]的更多信息(https://lihautan.com/Hydrating-text-content/)。那篇文章帮助我更多地了解这种奇怪的行为。 (2认同)
  • 谢谢。第二个选择帮助了我。 (2认同)

Moh*_*zas 12

在 html 元素上使用suppressHydrationWarning属性(不同)对我有用。根据以下文档,它仅在单一级别起作用:

https://reactjs.org/docs/dom-elements.html#suppressHydrationwarning