本文正在参加「金石计划」
const snapshot = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?);
一种读取和订阅其他数据源(不是使用React)的方式,可以和 selective hydration and time slicing 配合使用
-
subscribe
订阅回调函数, 返回取消订阅函数, store 改变时调用重新订阅然后重新渲染
-
getSnapshot
获取当前store的函数
必须返回一个cached value,(store不变每次调用返回相同的值)
-
getServerSnapshot
服务端渲染返回snapshot
订阅整个store
const state = useSyncExternalStore(store.subscribe, store.getSnapshot);
订阅某个域值
const selectedField = useSyncExternalStore(
store.subscribe,
() => store.getSnapshot().selectedField,
);
服务端必须序列化store
React会在hydration时使用snapshot以防内容不能匹配
const selectedField = useSyncExternalStore(
store.subscribe,
() => store.getSnapshot().selectedField,
() => INITIAL_SERVER_SNAPSHOT.selectedField,
);
订阅浏览器 API
网络状态和URL参数
import { useSyncExternalStore } from 'react';
export default function ChatIndicator() {
const isOnline = useSyncExternalStore(subscribe, getSnapshot);
return <h1>{isOnline ? '✅ Online' : '❌ Disconnected'}</h1>;
}
function getSnapshot() {
return navigator.onLine;
}
function subscribe(callback) {
window.addEventListener('online', callback);
window.addEventListener('offline', callback);
return () => {
window.removeEventListener('online', callback);
window.removeEventListener('offline', callback);
};
}
兼容
use-sync-external-store/shim useSyncExternalStore 和 user-space implementation
问答
-
The result of getSnapshot should be cached
getSnapshot 函数每次 render 返回了一个新对象
-
每次渲染 subscribe 都会执行
subscribe 定义在组件内部了
-
subscribe 定义在组件外部
function ChatIndicator() { const isOnline = useSyncExternalStore(subscribe, getSnapshot); // ... } // ✅ Always the same function, so React won't need to resubscribe function subscribe() { // ... } -
使用 useCallback
function ChatIndicator({ userId }) { const isOnline = useSyncExternalStore(subscribe, getSnapshot); // ✅ Same function as long as userId doesn't change const subscribe = useCallback(() => { // ... }, [userId]); // ... }
-