web-dev-qa-db-ja.com

React 16:警告:状態が原因で、サーバーHTMLの<div>に一致する<div>が含まれていると予想されます

SSRを使用すると次のエラーが発生します

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

問題は、コンポーネントのマウント時にブラウザの幅を確認し、代わりにモバイルバージョンをレンダリングするようにコンポーネントの状態を設定するときに、クライアントにあります。

ただし、サーバーはブラウザーの幅を認識しないため、コンテナーのデスクトップバージョンをデフォルト設定しています。

そのような場合にどう対処すればよいですか?どういうわけか、サーバー上のブラウザーの幅を検出し、クライアントに送信する前にモバイルコンテナーをレンダリングできますか?

編集:今のところ、コンポーネントがマウントされたときにコンテナをレンダリングすることにしました。このように、サーバー側とクライアント側の両方が、最初はこのエラーを防ぐものを何もレンダリングしません。

私はまだより良い解決策を開いています

6
Ivan M

これで問題が解決します。

// 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')
);
5
小弟调调
0
Martin Ždila

私の解決策は、 express-useragent のようなミドルウェアを使用してブラウザのユーザーエージェントを検出することです。

次に、サーバー側で、次のルールに従って{width, height}のようなviewsizeを作成します。

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のレスポンシブデザインです。

0
Ben P.P. Tung

現在受け入れられている回答は、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"))
0
sunknudsen