我对 useSyncExternalStore 进行了简要总结

useSyncExternalStore 的意思是什么?

在 React18 中,通过新增的 React Hook,可以订阅外部存储。

考察这个词什么时候可以使用。

使React Hook能够订阅外部存储。

在之前的資料中,不太明白,所以我想再多調查一下。經過進一步研究,文件中寫明了以下內容。

大多数的React组件在props、state和context中引用数据。
但是,有时也需要从React外部的数据源引用值。
在这种情况下,可以使用useSyncExternalStore来监视React外部数据源的存储,并引用存储的值。
例如)
用于保持状态的React外部库
可以订阅浏览器事件API的可变值和其变化。

因为我还不太明白,所以我阅读了一些文件,找到了以下描述。

    1. 如果您正在React中使用useState或useReducer来管理状态,建议您使用它们。useSyncExternalStore API主要用于与现有的非React代码集成的情况。

添加useSyncExternalStore的另一个原因是如果您需要订阅在浏览器中公开的并且会发生变化的值。

使用情景

经过调查研究后,我以自己的方式对所发现的一些事情进行了以下解释。我觉得现在对此有了一个比较清晰的想象。

非Reactコードと統合して状態管理をする必要がある場合

useState / useReducer / ライブラリ 等を用いても React で状態管理ができない場合

React を通さずにブラウザ側で起こった変化を管理する場合

使用方法

本次我们将讨论在 React 中读取难以检测的浏览器状态管理事件的情况,这也在文档中有提及,我们要做的是将网络连接是否处于活动状态显示在组件上。

浏览器通过navigator.onLine属性公开网络连接状态。由于这个值可能在React不知情的情况下被改变,因此需要使用useSyncExternalStore来读取它。

首先,我们将创建一个用于在页面上显示网络状况的框架。有关参数和返回值的详细信息,请参阅此处。

import { useSyncExternalStore } from 'react';

function useOnlineStatus() {
  // subscribe: ストアが変更されるたびに呼び出されるコールバックを登録する
  // getSnapshot: 現在のストアの値を返す
  return useSyncExternalStore(subscribe, getSnapshot);
}

export default function App() {
  const isOnline = useOnlineStatus();
  return <h1>{isOnline ? '✅ Online' : '❌ Disconnected'}</h1>;
}

要实现 getSnapshot 函数,需要从浏览器 API 中读取当前值。

function getSnapshot() {
  return navigator.onLine;
}

要实现subscribe函数,你需要将回调函数作为参数注册到相应的事件上,并返回一个函数来解除注册。当navigator.onLine发生变化时,浏览器会在window对象上触发在线和离线事件。

function subscribe(callback) {
  window.addEventListener('online', callback);
  window.addEventListener('offline', callback);
  return () => {
    window.removeEventListener('online', callback);
    window.removeEventListener('offline', callback);
  };
}

通过在 useSyncExternalStore 函数中将 subscribe 和 getSnapshot 作为参数传递,可以读取 navigator.onLine 的值并进行订阅以获取变化。结果将返回 True 或 False。

import { useSyncExternalStore } from 'react';

function subscribe(callback) {
  window.addEventListener('online', callback);
  window.addEventListener('offline', callback);
  return () => {
    window.removeEventListener('online', callback);
    window.removeEventListener('offline', callback);
  };
}

function getSnapshot() {
  return navigator.onLine;
}

function useOnlineStatus() {
  return useSyncExternalStore(subscribe, getSnapshot);
}

export default function App() {
  const isOnline = useOnlineStatus();
  return <h1>{isOnline ? '✅ Online' : '❌ Disconnected'}</h1>;
}

外传

顺便一提,如果使用 useEffect 进行实现,代码会像这样。
不过,根据我刚才解释的,似乎在 React 18 之后使用 useSyncExternalStore 更好。

import { useState } from 'react';

function useOnlineStatus() {
  // 理想的ではありません
  const [isOnline, setIsOnline] = useState(true);
  useEffect(() => {
    function updateState() {
      setIsOnline(navigator.onLine);
    }

    updateState();

    window.addEventListener('online', updateState);
    window.addEventListener('offline', updateState);
    return () => {
      window.removeEventListener('online', updateState);
      window.removeEventListener('offline', updateState);
    };
  }, []);
  return isOnline;
}

export default function App() {
  const isOnline = useOnlineStatus();
  return <h1>{isOnline ? '✅ Online' : '❌ Disconnected'}</h1>;
}

只使用 useEffect 实现时,与 useSyncExternalStore 相比可能会有一些缺点,但由于没有详细研究和时间限制,我希望稍后补充。。。

对于可读性而言,我认为使用 useSyncExternalStore 更好!

广告
将在 10 秒后关闭
bannerAds