React中的useSyncExternalStore使用
官方的解释是useSyncExternalStore
是一个让你订阅外部 store 的 React Hook。😄官方就爱打马虎眼,这样说随能一下子明白它的作用,接下来我们就来仔细的讲解下它的作用和应用场景。
useSyncExternalStore 作为 React 18 引入的一个 Hook,主要用于订阅外部数据源,确保在并发渲染下数据的一致性。它主要用于:
- 订阅浏览器 API(如 window.width)
- 订阅第三方状态管理库
- 订阅任何外部数据源
直接上例子:
- 基本语法
const state = useSyncExternalStore(subscribe, // 订阅函数getSnapshot, // 获取当前状态的函数getServerSnapshot // 可选:服务端渲染时获取状态的函数
);
- 实战 浏览器网络状态
//useOnlineStatus hooks
import { useSyncExternalStore } from 'react';export function useOnlineStatus() {const isOnline = useSyncExternalStore(subscribe, getSnapshot);return isOnline;
}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);};
}
- 实战浏览器窗口宽高
// useWindowSize hooks
function useWindowSize() {const getSnapshot = () => ({width: window.innerWidth,height: window.innerHeight});const subscribe = (callback) => {window.addEventListener('resize', callback);return () => window.removeEventListener('resize', callback);};return useSyncExternalStore(subscribe, getSnapshot);
}// 组建中 hooks使用
function NavComponent() {const { width, height } = useWindowSize();return (<div>Window size: {width} x {height}</div>);
}
- 实战 切换主题
function createThemeStore() {let theme = 'light';const listeners = new Set();return {subscribe(listener) {listeners.add(listener);return () => listeners.delete(listener);},getSnapshot() {return theme;},toggleTheme() {theme = theme === 'light' ? 'dark' : 'light';listeners.forEach(listener => listener());}};
}const themeStore = createThemeStore();function useTheme() {return useSyncExternalStore(themeStore.subscribe,themeStore.getSnapshot);
}function ThemeToggle() {const theme = useTheme();return (<button onClick={() => themeStore.toggleTheme()}>Current theme: {theme}</button>);
}
注意事项
-
保持一致性
- subscribe 函数应该返回清理函数
- getSnapshot 应该返回不可变的数据
-
避免频繁更新
- 考虑使用节流或防抖
- 实现选择性订阅机制
-
服务端渲染
- 提供 getServerSnapshot
- 确保服务端和客户端状态同步
-
内存管理
- 及时清理订阅
- 避免内存泄漏