web-dev-qa-db-ja.com

React SSRアプリとNext.jsでデバイスを検出する方法は?

webアプリケーションで、モバイル用とデスクトップブラウザー用の2つの異なるメニューを表示したいと思います。サーバーサイドレンダリングとライブラリ react-device-detect でNext.jsアプリケーションを使用しています。

これが CodeSandoxリンク です。

import Link from "next/link";
import { BrowserView, MobileView } from "react-device-detect";

export default () => (
  <div>
    Hello World.{" "}
    <Link href="/about">
      <a>About</a>
    </Link>
    <BrowserView>
      <h1> This is rendered only in browser </h1>
    </BrowserView>
    <MobileView>
      <h1> This is rendered only on mobile </h1>
    </MobileView>
  </div>
);

これをブラウザーで開き、モバイルに切り替えてビューでコンソールを見ると、次のエラーが発生します。

警告:テキストコンテンツが一致しませんでした。サーバー:「これはブラウザーでのみレンダリングされます」クライアント:「これはモバイルでのみレンダリングされます」

これは、サーバーによるレンダリングがブラウザーを検出し、クライアントでは彼がモバイルデバイスであるために発生します。私が見つけた唯一の回避策は、両方を生成して次のようなCSSを使用することです。

.activeOnMobile {
  @media screen and (min-width: 800px) {
    display: none;
  }
}

.activeOnDesktop {
  @media screen and (max-width: 800px) {
    display: none;
  }
}

ライブラリの代わりに、私はこの方法があまり好きではありません。誰かがSSRアプリのデバイスタイプを反応コードで直接処理するための良い習慣を知っていますか?

5
Benjamin Sx

サーバーとクライアントの両方で実行されるため、ページでgetInitialPropsを使用し、最初にWebページのリクエストを取得しているかどうかを検出することによってデバイスタイプを取得することで、それを実行する必要があると思います(したがって、まだサーバー)、または再レンダリングする場合(つまり、クライアント上にある場合)。

// index.js

IndexPage.getInitialProps = ({ req }) => {
  let userAgent;
  if (req) { // if you are on the server and you get a 'req' property from your context
    userAgent = req.headers['user-agent'] // get the user-agent from the headers
  } else {
    userAgent = navigator.userAgent // if you are on the client you can access the navigator from the window object
  }
}

これで、正規表現を使用して、デバイスがモバイルかデスクトップかを確認できます。

// still in getInitialProps

let isMobile = Boolean(userAgent.match(
  /Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i
))

return { isMobile }

これで、trueまたはfalseを返すisMobileプロップにアクセスできます

const IndexPage = ({ isMobile }) => {
  return ( 
    <div>
     {isMobile ? (<h1>I am on mobile!</h1>) : (<h1>I am on desktop! </h1>)} 
    </div>
  )
}

こちらの記事からこの回答を得ました お役に立てば幸いです

3
Dylanbob211