Gab*_*ira 10 javascript reactjs next.js
我试图在 next.js 中执行一个简单的算法,但遇到了水合错误。
\n这是我正在使用的代码:
\nimport numeros from "../../functions/numberGenerators.js"\n\nexport default function teste(){\n let number = numeros()\n return number.map(n => \n <div key={n}>\n Number: {n}\n </div>)\n}Run Code Online (Sandbox Code Playgroud)\r\n和:
\nexport default function megaSena(qtde = 6){\n let listNumbers = []\n while(listNumbers.length <= qtde - 1){\n const numeroRandom = parseInt(Math.random() * 60) + 1\n if (!listNumbers.includes(numeroRandom)){\n listNumbers.push(numeroRandom)\n }\n }\n return listNumbers\n}Run Code Online (Sandbox Code Playgroud)\r\n我遇到以下错误:
\n1\xc2\xb0 - 错误:水合失败,因为初始 UI 与服务器上呈现的内容不匹配。
\n2\xc2\xb0 - 错误:文本内容与服务器呈现的 HTML 不匹配。
\n3\xc2\xb0 - 错误:水合失败,因为初始 UI 与服务器上呈现的内容不匹配。
\n4\xc2\xb0 - 错误:补水时出现错误。由于错误发生在 Suspense 边界之外,因此整个根将切换到客户端渲染。
\n我可以做什么来解决这个问题?
\ntwi*_*wiz 24
这些错误消息本质上都说了同样的事情:
来自服务器的 HTML 与您的应用程序呈现的内容不匹配。
当teste被调用时,它并不总是返回相同的东西。它旨在显示随机数。
这意味着每次 teste渲染时都会显示不同的数字列表。
当将服务器端渲染(SSR)与 NextJS 等框架一起使用时,它使用的是React Hydration。这只是一个花哨的词,表示 React 正在研究如何获取从 HTML 文件渲染的 DOM 结构并将其转换为正在运行的单页应用程序 (SPA)。
为了使其正常工作,React Hydration 要求服务器中的 HTML 与客户端应用程序呈现的内容完全匹配。
所以在你的场景中,这就是发生的事情:
teste,生成一个随机数字数组并渲染它。teste,生成一个新的随机数字数组并呈现它。修复方法很简单,但需要您注意何时需要或不需要。
常见的方法是确保useEffect()服务器和客户端在水合过程中渲染相同的内容,并且仅在客户端上渲染动态内容。
最简单的方法就是不渲染任何内容。使用您的代码,看起来像这样:
import React from "react";
export default function Teste() {
const [hydrated, setHydrated] = React.useState(false);
React.useEffect(() => {
setHydrated(true);
}, []);
if (!hydrated) {
// Returns null on first render, so the client and server match
return null;
}
let number = numeros();
return number.map((n) => <div key={n}>Number: {n}</div>);
}
Run Code Online (Sandbox Code Playgroud)
这是为了确保第一次Teste渲染时它会返回null。
第一个渲染是服务器用来生成 HTML 文件的内容,也是客户端应用程序将用于“水合”过程的内容。
在第一次运行期间,hydrated将具有默认值false,这将导致组件返回null。同样在第一次运行中,useEffect()将调用setHydrated(true),这将在第一次渲染完成后触发第二次渲染。
当第二次渲染运行时,应用程序已经水合了,因此无需再担心发生错误。此时hydrated将为true,因此随机数将正常渲染。
如果您想了解有关 React 水合的更多信息,我写了一篇关于修复这些类型的错误的博客文章。
我还发布了一个 NPM 包,有助于简化处理这些类型的水合错误:react-Hydration-provider
要使用 修复错误react-hydration-provider,您的代码将如下所示:
import { HydrationProvider, Client } from "react-hydration-provider";
function App() {
return (
<HydrationProvider>
<Client>
<Teste />
</Client>
</HydrationProvider>
);
}
function Teste() {
let number = numeros();
return number.map((n) => <div key={n}>Number: {n}</div>);
}
Run Code Online (Sandbox Code Playgroud)
这只会Teste在应用程序水合后才在客户端进行渲染。
您还可以做一些更复杂的事情,如下所示:
import { HydrationProvider, Server, Client } from "react-hydration-provider";
function App() {
return (
<HydrationProvider>
<Teste />
</HydrationProvider>
);
}
function Teste() {
let number = numeros();
return number.map((n) => (
<div key={n}>
<span>Number: </span>
<Client>{n}</Client>
<Server>Loading...</Server>
</div>
));
}
Run Code Online (Sandbox Code Playgroud)
这将允许您的应用程序最初为每个数字呈现一条加载消息,然后在应用程序完成水合过程后将其替换为随机数字。
正如@milad-amirvafa 所说,
注释掉代码的某些部分以获取导致水合错误的元素,然后添加一个以 false 作为初始状态的状态钩子,如下所示const [hydrated, setHydrated] = useState(false);
然后在 useEffect 挂钩中将该状态设置为 true,将水合状态添加到导致错误的组件中。您的代码应如下所示:
const Component = () => {
const [hydrated, setHydrated] = useState(false);
useEffect(() => {
setHydrated(true);
},[])
return (
<>
{hydrated && <div>The element which throws error</div>}
</>
)}
export default Component;
Run Code Online (Sandbox Code Playgroud)