【问题标题】:React 16: Warning: Expected server HTML to contain a matching <div> in <div> due to StateReact 16:警告:由于状态,预期服务器 HTML 在 <div> 中包含匹配的 <div>
【发布时间】:2017-10-21 17:13:40
【问题描述】:

我在使用 SSR 时遇到以下错误

Warning: Expected server HTML to contain a matching &lt;div&gt; in &lt;div&gt;.

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

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

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

编辑:现在我决定在组件安装时渲染容器。这样一来,服务器端和客户端都不会渲染任何东西来阻止这个错误。

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

【问题讨论】:

  • stackoverflow.com/questions/46443652/… 重复。确保您使用React.hydrate() 方法是因为您使用的是SSR。如果不使用React.render()。您还可以在渲染元素上使用 suppressHydrationWarning={true} 属性。但不要过度使用它。

标签: reactjs isomorphic-javascript client-hints


【解决方案1】:

这将解决问题。

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

【讨论】:

  • 是的。最后,您应该必须重新启动服务器。但是,最后,如果您对客户端和服务器使用相同的组件,则不会有任何区别。但是,如果您还想在服务器更新时自动重新加载浏览器,您仍然需要自动重新加载服务器。
  • 这如何解决问题?这个好像开启了热模块重载,客户端渲染只需要使用SPA的方式,但是在生产构建中,还是会出现标记不匹配的问题?
  • 在 nextjs 中呢,因为 public 文件夹中没有 root id
【解决方案2】:

盖茨比

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

【讨论】:

  • 来自文档:DEV_SSR - Server-side render (SSR) pages on full reloads during develop. Helps you detect SSR bugs and fix them without needing to do full builds. 这修复了警告但禁用了其他功能。
  • 是的,你是对的,正如我所说,“你可以禁用这个标志”
  • 这只是解决开发模式警告,如果您在生产中进行服务器端渲染,这将无法避免标记差异。
【解决方案3】:

当前接受的答案不能很好地与 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"))

【讨论】:

  • 这个解决方案对我有用,React/React-DOM ^16.13.0
【解决方案4】:

此消息也可能是由于错误代码无法在您的 SSR 和 CSR 之间呈现一致的内容,因此 hydrate 无法解决。

例如 SSR 返回:

...
<div id="root">
   <div id="myDiv">My div content</div>
</div>
...

当企业社会责任回归时:

...
<div id="root">
    <div id="anotherDiv">My other div content</div>
</div>
...

在这种情况下,最好的解决方案是不安装库或关闭hydrate,而是实际修复代码中的不一致。

index.js 中临时删除&lt;script src="/react-bundle-path.js"&gt;&lt;/script&gt; 有助于将SSR 呈现的确切内容与CSR hydrate 呈现的内容进行比较。

【讨论】:

    【解决方案5】:

    【讨论】:

    • 您提供的链接已失效,请在此处粘贴相关信息以供日后参考。
    • @CorwinCZ 感谢您的通知。我已经更新了 ling 并添加了另一个。
    【解决方案6】:

    我的解决方案是使用像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 中的响应式设计。

    【讨论】:

      猜你喜欢
      • 2018-03-08
      • 2021-01-15
      • 2020-07-04
      • 2018-01-03
      • 2021-08-11
      • 2021-08-19
      • 2021-08-16
      • 2021-09-05
      • 1970-01-01
      相关资源
      最近更新 更多