日本語版
最新ニュース
科学&テクノロジー

LocalStorage で useSyncExternalStore を使用する例

React開発では、アプリケーションの状態を外部データソース、特にLocalStorageなどのソリューションと同期させる必要があることがよくあります。React 18以降、新しいフックと呼ばれるものが追加されました。 useSyncExternalStore この同期を容易にするために導入されました。このフックを使用する具体的な例を説明します。 なぜ使うのか useSyncExternalStore? useSyncExternalStore 複数のコンポーネント インスタンス間で共有される可能性のある外部ソースからデータを読み取り、同期するように設計されています。これにより、アプリケーションはこれらのデータ ソースの変更に効率的に反応し、状態の一貫性を確保して、スムーズなユーザー エクスペリエンスを提供できます。 具体的な例: アプリケーションテーマを LocalStorage と同期する この例では、ユーザーが明るいテーマと暗いテーマを切り替えることができるReactアプリケーションを作成します。選択されたテーマはセッション間で保持されるようにLocalStorageに保存され、 useSyncExternalStore 異なるブラウザタブ間でも、アプリケーション全体でテーマの同期を管理します。 useThemeStore 最初のステップは、LocalStorage のリッスンと更新を処理するカスタム フックを作成することです。 import { useSyncExternalStore } from "react"; type Theme = "light" | "dark"; const THEME_STORAGE_KEY = "app-theme";…

LocalStorage で useSyncExternalStore を使用する例

1724661756
2024-08-23 10:35:58

React開発では、アプリケーションの状態を外部データソース、特にLocalStorageなどのソリューションと同期させる必要があることがよくあります。React 18以降、新しいフックと呼ばれるものが追加されました。 useSyncExternalStore この同期を容易にするために導入されました。このフックを使用する具体的な例を説明します。

なぜ使うのか useSyncExternalStore?

useSyncExternalStore 複数のコンポーネント インスタンス間で共有される可能性のある外部ソースからデータを読み取り、同期するように設計されています。これにより、アプリケーションはこれらのデータ ソースの変更に効率的に反応し、状態の一貫性を確保して、スムーズなユーザー エクスペリエンスを提供できます。

具体的な例: アプリケーションテーマを LocalStorage と同期する

この例では、ユーザーが明るいテーマと暗いテーマを切り替えることができるReactアプリケーションを作成します。選択されたテーマはセッション間で保持されるようにLocalStorageに保存され、 useSyncExternalStore 異なるブラウザタブ間でも、アプリケーション全体でテーマの同期を管理します。

useThemeStore

最初のステップは、LocalStorage のリッスンと更新を処理するカスタム フックを作成することです。

import { useSyncExternalStore } from "react";

type Theme = "light" | "dark";

const THEME_STORAGE_KEY = "app-theme";

const getThemeFromLocalStorage = (): Theme => {
  return (localStorage.getItem(THEME_STORAGE_KEY) as Theme) || "light";
};

const subscribe = (callback: () => void): (() => void) => {
  window.addEventListener("storage", callback);
  return () => {
    window.removeEventListener("storage", callback);
  };
};

const useThemeStore = (): [Theme, (newTheme: Theme) => void] => {
  const theme = useSyncExternalStore(subscribe, getThemeFromLocalStorage);

  const setTheme = (newTheme: Theme) => {
    localStorage.setItem(THEME_STORAGE_KEY, newTheme);
    window.dispatchEvent(new Event("storage"));
  };

  return [theme, setTheme];
};

export default useThemeStore;
  • getThemeFromLocalStorage この関数は、LocalStorage から読み取り、現在のテーマを取得する役割を担います。
  • subscribe この関数は、ブラウザのストレージ イベントを使用して、LocalStorage に加えられた変更をリッスンします。このメカニズムにより、変更が別のタブから発生した場合でも、アプリケーション内のテーマの状態を更新できます。
  • ついに、 useThemeStore これはアプリケーション内で使用されるフックであり、現在のテーマの値を取得できます(theme) を変更したり (setTheme)。
    ご覧の通り、 useSyncExternalStore 加入者(subscribe) と LocalStorage 読み取り関数 (getThemeFromLocalStorage) が正しく機能する必要があります。

応用

具体的な例を挙げてみます。 useThemeStore テーマを切り替えるためのフック ThemeToggler コンポーネント。このソリューションの利点は、すべてのブラウザ タブでテーマが変更されることです。

// Header.tsx
import React from "react";
import useThemeStore from "./useThemeStore";
import styled from "styled-components";

const StyledHeader = styled.header themeType: "light" | "dark" }>`
  padding: 1rem;
  text-align: center;
  background-color: ${({ themeType }) =>
    themeType === "light" ? "#f0f0f0" : "#222"};
  color: ${({ themeType }) => (themeType === "light" ? "#000" : "#fff")};
`;

const Header: React.FC = () => {
  const [theme] = useThemeStore();

  return (
    StyledHeader themeType={theme}>
      h1>Current Theme: {theme.charAt(0).toUpperCase() + theme.slice(1)}h1>
    StyledHeader>
  );
};

export default Header;
//  Footer.tsx
import React from "react";
import useThemeStore from "./useThemeStore";
import styled from "styled-components";

const StyledFooter = styled.footer themeType: "light" | "dark" }>`
  padding: 1rem;
  text-align: center;
  background-color: ${({ themeType }) =>
    themeType === "light" ? "#e0e0e0" : "#111"};
  color: ${({ themeType }) => (themeType === "light" ? "#000" : "#fff")};
  position: absolute;
  bottom: 0;
  width: 100%;
`;

const Footer: React.FC = () => {
  const [theme] = useThemeStore();

  return (
    StyledFooter themeType={theme}>
      p>Footer Content - Theme is {theme}p>
    StyledFooter>
  );
};

export default Footer;
// ThemeToggler.tsx
import React from "react";
import useThemeStore from "./useThemeStore";
import styled from "styled-components";

const ToggleButton = styled.button themeType: "light" | "dark" }>`
  padding: 0.5rem 1rem;
  font-size: 1rem;
  cursor: pointer;
  background-color: ${({ themeType }) =>
    themeType === "light" ? "#000" : "#fff"};
  color: ${({ themeType }) => (themeType === "light" ? "#fff" : "#000")};
  border: none;
  border-radius: 4px;
  transition:
    background-color 0.3s ease,
    color 0.3s ease;

  &:hover {
    background-color: ${({ themeType }) =>
      themeType === "light" ? "#333" : "#ddd"};
  }
`;

const ThemeToggler: React.FC = () => {
  const [theme, setTheme] = useThemeStore();

  const toggleTheme = () => {
    setTheme(theme === "light" ? "dark" : "light");
  };

  return (
    ToggleButton themeType={theme} onClick={toggleTheme}>
      Switch to {theme === "light" ? "Dark" : "Light"} Theme
    ToggleButton>
  );
};

export default ThemeToggler;
// App.tsx
import React from "react";
import Header from "./Header";
import ThemeToggler from "./ThemeToggler";
import Footer from "./Footer";
import useThemeStore from "./useThemeStore";
import styled from "styled-components";

const AppContainer = styled.div themeType: "light" | "dark" }>`
  min-height: 100vh;
  background-color: ${({ themeType }) =>
    themeType === "light" ? "#ffffff" : "#333333"};
  color: ${({ themeType }) => (themeType === "light" ? "#000000" : "#ffffff")};
  display: flex;
  flex-direction: column;
  align-items: center;
  transition: all 0.3s ease;
  position: relative;
  padding-bottom: 3rem; // To ensure footer is visible
`;

const App: React.FC = () => {
  const [theme] = useThemeStore();

  return (
    AppContainer themeType={theme}>
      Header />
      ThemeToggler />
      Footer />
    AppContainer>
  );
};

export default App;

その他の具体的な使用例 useSyncExternalStore

  • 接続ステータスの追跡: ユーザーの接続ステータス (ログインまたはログアウト) を追跡するために使用できます。たとえば、ユーザーが 1 つのタブでログアウトすると、この変更は開いている他のすべてのタブに自動的に反映されます。
  • リアルタイムのデータ同期: API または WebSocket を介して、すべてのデータ ビューが最新バージョンの外部データと同期されることを保証できます。
  • 通知管理: 異なるコンポーネントまたはブラウザ タブ間でグローバル通知を同期するために使用できます。
  • 電子商取引アプリケーションでのショッピング カートの同期: 複数のコンポーネントまたはブラウザー タブ間でショッピング カートの内容を同期できます。
  • …などなど。

結論

useSyncExternalStore は、アプリケーションの状態を LocalStorage などの外部データ ソースと同期するための強力なツールです。このフックを使用すると、複数のコンポーネント間、またはアプリケーションの複数のインスタンス間で共有データを処理できる React アプリケーションを作成できます。

使用することで useThemeStoreでは、LocalStorage を使用してアプリケーション テーマを保存および同期し、ページを再読み込みしたりタブを切り替えたりしてもスムーズで一貫したユーザー エクスペリエンスを確保する方法を説明しました。

出典と参考文献

#LocalStorage #で #useSyncExternalStore #を使用する例

執筆者について: nipponese

Nipponese News編集部は、国内外のニュースを日本語で分かりやすくお届けします。