React 16:警告:由于State,预期服务器HTML在<div>中包含匹配的<div>

时间:2017-10-21 17:13:41

标签: reactjs isomorphic-javascript

我使用SSR

收到以下错误

Warning: Expected server HTML to contain a matching <div> in <div>.

在检查组件装载时的浏览器宽度,然后设置组件的状态以呈现其移动版本时,问题出现在客户端上。

但是服务器默认了容器的桌面版本,因为它不知道浏览器的宽度。

我该如何处理这种情况?我可以以某种方式检测服务器上的浏览器宽度并在发送到客户端之前呈现移动容器吗?

编辑:现在我决定在组件安装时渲染容器。这样,服务器端和客户端都不会在最初时阻止此错误。

我仍然愿意接受更好的解决方案

6 个答案:

答案 0 :(得分:17)

盖茨比

最近的 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

答案 1 :(得分:2)

这将解决问题。

// 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')
);

答案 2 :(得分:2)

当前接受的答案不适用于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"))

答案 3 :(得分:0)

答案 4 :(得分:0)

我的解决方案是使用像express-useragent这样的中间件来检测浏览器用户代理。

然后,在服务器端,按照以下规则创建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中的响应式设计。

答案 5 :(得分:0)

此消息也可能是由于错误代码无法在您的 SSR 和 CSR 之间呈现一致的内容而导致的,因此 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,而是实际修复代码中的不一致性。

<script src="/react-bundle-path.js"></script> 中临时删除 index.js 有助于比较 SSR 呈现的确切内容与 CSR hydrate 呈现的内容。