使用SSR时出现以下错误:
警告: 期望服务器HTML在<div>中包含匹配的<div>。
问题出现在组件挂载时,在客户端检查浏览器宽度,然后设置组件的状态以渲染其移动版本。
但是服务器默认为桌面容器的版本,因为它不知道浏览器的宽度。
如何处理这种情况?我是否可以在服务器上某种方式检测浏览器宽度,并在发送到客户端之前呈现移动容器?
编辑:目前,我已决定在组件挂载时呈现容器。 这样,服务器和客户端都不会最初呈现任何内容,从而防止此错误。
我仍然愿意接受更好的解决方案。
使用SSR时出现以下错误:
警告: 期望服务器HTML在<div>中包含匹配的<div>。
问题出现在组件挂载时,在客户端检查浏览器宽度,然后设置组件的状态以渲染其移动版本。
但是服务器默认为桌面容器的版本,因为它不知道浏览器的宽度。
如何处理这种情况?我是否可以在服务器上某种方式检测浏览器宽度,并在发送到客户端之前呈现移动容器?
编辑:目前,我已决定在组件挂载时呈现容器。 这样,服务器和客户端都不会最初呈现任何内容,从而防止此错误。
我仍然愿意接受更好的解决方案。
这将解决问题。
// Fix: Expected server HTML to contain a matching <a> in
const renderMethod = module.hot ? ReactDOM.render : ReactDOM.hydrate;
renderMethod(
<BrowserRouter>
<RoutersController data={data} routes={routes} />
</BrowserRouter>,
document.getElementById('root')
);
Gatsby的一个最新功能标志(于2020年12月的v2.28版本中引入)可以在开发环境下实现服务器端渲染页面。
该标志默认设置为true
。此时,您可能会在控制台看到以下错误信息:
Warning: Expected server HTML to contain a matching <div> in <div>.
您可以在 gatsby.config.js
文件中禁用此标志:
module.exports = {
flags: {
DEV_SSR: false,
}
}
文档: https://www.gatsbyjs.com/docs/reference/release-notes/v2.28/#feature-flags-in-gatsby-configjs
功能标志在Gatsby配置文件中的特性。这条消息也可能是由于坏代码导致的,它不能在服务器端呈现一致的内容和客户端呈现一致的内容, 因此hydrate
无法解析。
例如 SSR 返回:
...
<div id="root">
<div id="myDiv">My div content</div>
</div>
...
当CSR返回时:
...
<div id="root">
<div id="anotherDiv">My other div content</div>
</div>
...
hydrate
,而是实际修复代码中的不一致性。index.js
中删除<script src="/react-bundle-path.js"></script>
可以帮助比较SSR渲染的确切内容和CSR hydrate
渲染的内容。目前被接受的答案与TypeScript不兼容。以下是适用于我的方法。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
</body>
</html>
import React from "react"
import { hydrate, render } from "react-dom"
import BrowserRouter from "./routers/Browser"
const root = document.getElementById("root")
var renderMethod
if (root && root.innerHTML !== "") {
renderMethod = hydrate
} else {
renderMethod = render
}
renderMethod(<BrowserRouter />, document.getElementById("root"))
来自 https://github.com/vercel/next.js/discussions/17443#discussioncomment-87097
只应在浏览器中运行的代码应该在
useEffect
中执行。这是必需的,因为第一次渲染应该与服务器的初始渲染匹配。如果您操纵该结果,则会创建不匹配,React 将无法成功地进行页面水合。当您在
useEffect
中运行仅在浏览器中运行的代码(例如尝试访问window
)时,它将发生在水合之后
HTTP客户端提示可以帮助您解决这个问题。
viewsize
,如{width, height}
。if (ua.isMobile) {
return {width: 360, height: 480}
}
if (ua.isDesktop) {
return {width: 768, height: 600}
}
return {width: 360, height: 480} // default, and for bot
然后,在SSR中它仍然以某种方式是响应式设计。
export default function RootLayout({ children }) {
return (
<>
<html lang="en">
<body className={inter.className}>
<Toaster position="top-right" reverseOrder={false} toastOptions={{ duration: 1000 }} />
<StoreProvider>
{children}
</StoreProvider>
</body>
</html>
</>
)
}
React.hydrate()
方法,否则请使用React.render()
。您还可以在呈现的元素上使用suppressHydrationWarning={true}
属性。但不要过度使用它。 - AxeEffect