日10:ダークモードでボタンをレンダリングするバグを修正するが、光モードでGoogleマップを埋め込む



TLドクター
WebアプリケーションのUIがユーザーのローカル時間に依存する場合は、次のような静的サイトジェネレータを確認します.jsはクライアント側でのみHTMLページを生成します.
たとえば、反応アプリのUIが自動的にユーザーの現地時間で午後6時後に暗いモードになると、使用するuseEffect() HTMLページを生成するフック.それ以外の場合は、上記のイメージに示すように、ボタン(静的に生成される)は、暗いモードでレンダリングされるかもしれませんが、埋め込まれたGoogleマップ(クライアント側でレンダリングされます)は、ライトモードで表示されます.

文脈の導入
私はGoogleマップのユーザー体験を向上させるGoogleマップのフルスクリーンを埋め込む私の理想的な地図アプリと呼ばれるWebアプリを作っている.(詳しくは次の記事を参照)


つの改善は、自動的にユーザーの現地時間で午後6時以降の暗いモードをオンにすることです.アプリは、ユーザーが外出しているときにモバイルデバイス上で使用するためのものです.私は、手動で暗いモードでオンとオフを切り替えることなく、そのUIは昼間明るいと夜間に暗いしたい.(詳しくは次の記事を参照)


私はまた、埋め込まれたGoogleマップの上部に表示されるボタンのダークモードのカラースキームを設計しました


ので、埋め込まれたGoogleマップと一緒に午後6時以降に暗いモードで表示されるようにボタンのレンダリングをコーディングした後、私はCloudflare Pages . CloudFlareページはそれぞれの展開に固有のURLを割り当て、ブラウザがどのように作っているかをチェックできる.

バグ
日本では午後3時頃でした.ので、URLを訪問すると、次のイメージの左半分のように私の理想的な地図アプリの光モードのバージョンを表示する必要があります

私の理想的な地図アプリの光モードUI(左)とダークモードUI(右)(著者によるスクリーンショット)
しかし、私はこれを見ました:

暗い灰色の雲のボタンを光モードで地図を
マップは予想通りに光モードでレンダリングされます.しかし、ボタンは暗い雲のように見えます.
このバグで展開を見ることができますhttps://05da7f84.mima.pages.dev . あなたの現地時間が午前6時から午後6時の間であれば、これらの雨雲が見えます.
ところで、私がボタンを雲のようにした理由については、次の記事を見てください.


暗モードを光モードで共存させるにはどうすればよいか?本当に頭を掻きました.

root原因:プリレンダリング
理由は、ボタンの前のレンダリングですNext.js , 私は理想的なマップのアプリを構築するために使用している反応フレームワーク.
次.デフォルトですべてのページをレンダリングするNext.js Documentation ). つまり、Web開発者がコードをアップロードすると、サーバーはすぐにJavaScriptを実行してHTMLページを生成します.ユーザーがWebアプリケーションにログオンすると、これらの事前に構築されたHTMLページがブラウザに送信されます.
(もしあなたが前に何を書いているのかについて自信がないならば、私が以前に1年以上前に同じ質問をした後に書いた記事を見てください.Kudamatsu 2020 ).
私に起こったことは以下の通りでした:サーバーの時計が午後6時過ぎだったとき、私はCloudFlare Pages Serverにウェブアプリを配備しましたCloudflare has many servers across the world ). これにより、サーバは暗モードでボタンを構築しました.
しかし、埋め込まれたGoogleマップは常にブラウザによってレンダリングされます(この事実は明確にGoogle Mapsプラットフォームのドキュメントのどこにでも書かれていませんが、それは多くのようなStarkov 2017 ). それで、私が私の現地時間で午後3時ごろ配備されたウェブアプリを訪問したとき、地図は光モードでレンダリングされました.
その結果、ダークモードのボタンがライトモードで地図上に表示されました.
問題は、別のタイムゾーンまたは組み込みのGoogleマップのクライアント側レンダリングにサーバーへの配置に固有ではありません.Webアプリケーションが配備される時間は、ユーザーがアプリケーションにアクセスする時間とは常に異なるので、ユーザーは意図していないUIを見ることができます.
授業を習う.WebアプリケーションのUIがユーザーのローカル時間に依存している場合は、次のような静的サイトジェネレータを使用するように注意してください.jsとGatsby .

回避策: useeffect ()
そこで、サイトのアクセスをするユーザーの時点で、サーバー側ではなく、ブラウザでボタンをレンダリングする方法を見つける必要があります.
多分、私は次に使用しないでください.しかし、代わりにCreate Reactionアプリを使用する(クライアント側のレンダリングを許可する).でも次は.JSは、Web開発者のための他の多くの便利な機能を持って、私はWebアプリを構築するためにそれを使用するために使用されてTriangulum Color Picker で次へ.JS .だから私は別の反応フレームワークに切り替える必要はありません.
半日以上のかなりの闘争の後、私は解決されたDong (2020) , これはより一般的にComeau (2021) .
トリックはuseEffect() フック.私は、内部のコードがuseEffect() フックはブラウザでのみ実行され、事前にレンダリングされたコンポーネントがサーバーに反応します.
それが私のケースのために働く方法は、ここにあります.

バグを生成するコード
pages/index.js ( Next . jsはindex.html 最初に、私は最初に以下のコード(関連する部分だけを示していました)を持っていました.
// pages/index.js

import {NightModeProvider} from '../context/NightModeContext';
import MenuButton from '../components/MenuButton';
import SearchButton from '../components/SearchButton';
import LocatorButton from '../components/LocatorButton';
import SavePlaceButton from '../components/SavePlaceButton';
import Map from '../components/Map';

function HomePage() {
  return (
    <>
      <NightModeProvider>
        <MenuButton />
        <SearchButton />
        <LocatorButton />
        <SavePlaceButton />
        <Map /> {/* where Google Maps will be embedded */}
      </NightModeProvider>
    </>
  );
}

export default HomePage;

つのボタンと<Map> Googleマップを埋め込むコンポーネント.これらの5つのコンポーネントのそれぞれにダークモードをオン/オフさせるには<NightModeProvider> , これは反応コンテキストプロバイダーから生成されます.
// context/NightModeContext.js

import {createContext} from 'react';

const NightModeContext = createContext();

export function NightModeProvider(props) {
  let nightMode;
  const currentTime = new Date();
  const currentHour = currentTime.getHours();
  if (currentHour < 6 || currentHour >= 18) {
    nightMode = true;
  } else {
    nightMode = false;
  }
  return <NightModeContext.Provider value={nightMode} {...props} />;
}
ローカル時間が午後6時と午前6時の間かどうかチェックします.もしそうならば、それはセットしますnightMode あるtrue を子要素に渡す.(詳細は3.2節を参照ください.

バグを修正するためのコード
ボタンのコンポーネントを事前にレンダリングしないようにするには、clientSideRendering は最初にfalse . 次に、ボタンコンポーネントをclientSideRendering is true :
import {useState} from 'react'; // ADDED
...
function HomePage() {
  const [clientSideRendering, setClientSideRendering] = useState(false); // ADDED
  return (
    <>
      <NightModeProvider>
        {/* REVISED FROM HERE */}
        {clientSideRendering && <MenuButton />}     
        {clientSideRendering && <SearchButton />}  
        {clientSideRendering && <LocatorButton />} 
        {clientSideRendering && <SavePlaceButton />} 
        {/* REVISED UNTIL HERE */}
        <Map />
      </NightModeProvider>
    </>
  );
}
...
このように、配備されると、サーバーはこれらのボタンコンポーネントをレンダリングしませんclientSideRendering is false .
ユーザーのブラウザでボタンをレンダリングするコードを実行できるようにするにはclientSideRendering into true インサイドuseEffect() フック
import {useState, useEffect} from 'react'; // REVISED
...
function HomePage() {
  const [clientSideRendering, setClientSideRendering] = useState(false);

  // ADDED FROM HERE
  useEffect(() => {
    setClientSideRendering(true);
  }, []);
  // ADDED UNTIL HERE

  return (
    <>
      <NightModeProvider>
        {clientSideRendering && <MenuButton />}
        {clientSideRendering && <SearchButton />}
        {clientSideRendering && <LocatorButton />}
        {clientSideRendering && <SavePlaceButton />}
        <Map />
      </NightModeProvider>
    </>
  );
}
内部のコードuseEffect() フックは、戻り値として列挙されたコンポーネントがレンダリングされた後にのみ実行されます.そして、setClientSideRendering 状態変数の変更、すべてのコンポーネントは、すべてのボタン(ユーザーの現地時間に基づいてレンダリング)の新しい値に基づいて再レンダリングされます.
このプロセスは、Webアプリケーションが配備される時間に基づいて、ライトまたはダークモードでボタンをレンダリングすることを回避するコンポーネントをサーバーが事前にレンダリングするときに発生しません.
最後の接触useEffect() フックは、ユーザーがページを訪問した後に一度だけ実行する必要があります.したがって、useEffect() フックは空の配列、すなわち、[] (参照)React documentation 詳細は).
6 pm以降、次のUIを取得します.

暗いモードでダークモードボタンを内蔵Googleマップ
こちらa demo hosted by Cloudflare Pages . ローカルモードで午後6時以降に暗いモードのUIを表示しない場合は、この記事にコメントを投稿してバグレポートをファイルします.
最後に、私は理想的な地図アプリのボタンで行われます.次のステップは、これらのボタンに機能を追加することです.私は、地図上のユーザーの現在の位置が表示されますロケータボタン(フライト離陸アイコンを1つ)を起動します.

参考文献
コーム、ジョシュ(2021)The Perils of Rehydration ”, ヨシュワメー.2021年5月30日
ドン、ハウ(2020)Render client-side only component in Next.js ”, Haoの学習ログ2020年11月30日.
下松夏Beyond create-react-app: Why you might want to use Next.js or Gatsby instead ”, 2020年11月30日京都のweb dev調査
Starkov , Ivan ( 2017 )It is expected, google map api, over which this component build does not support server tile rendering... ”, GoogleマップのためのGithub問題は反応します.