拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Preact Query 状态恢复信号机制:IsRestoringProvider 与 useIsRestoring 全解析

Preact Query 状态恢复信号机制IsRestoringProvider 与 useIsRestoring 全解析【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/query导读在 TanStack Query 的 Preact 适配层tanstack/preact-query中IsRestoringProvider是一个承载持久化查询客户端是否正在恢复这一布尔信号的 Context Provider。它与配套的 useIsRestoring Hook 一起被PersistQueryClientProvider用来向整棵组件树广播恢复状态并被useQuery及其衍生 Hook 内部消费以避免持久化数据恢复与查询挂载之间的竞态条件race condition。读完本文你将掌握该 Provider 的定义方式、在持久化插件中的驱动逻辑以及它如何在底层影响查询订阅与乐观结果计算。一、IsRestoringProvider是什么从 IsRestoringProvider.ts 的源码可以看到它的类型签名极简const IsRestoringProvider: Providerboolean IsRestoringContext.Provider;它是 Preact 内置createContext所创建上下文的.Provider。定义位于 IsRestoringProvider.ts:19完整定义代码如下import { createContext } from preact import { useContext } from preact/hooks const IsRestoringContext createContext(false) export const useIsRestoring () useContext(IsRestoringContext) export const IsRestoringProvider IsRestoringContext.Provider从源码结构看这是一个布尔型 Context默认值为false即当前没有正在执行的恢复流程。Provider 的职责非常单一——向其子树提供持久化客户端当前是否正在被恢复的布尔值真正的读取方是配套导出的useIsRestoringHook。二、谁在驱动它PersistQueryClientProvider的恢复流程IsRestoringProvider本身不包含任何恢复逻辑它是被持久化查询客户端插件消费的信号载体。在 Preact 生态中真正的驱动者是 PersistQueryClientProvider.tsx。关键实现如下const [isRestoring, setIsRestoring] useState(true) useEffect(() { const options { ...refs.current.persistOptions, queryClient: props.client, } if (!didRestore.current) { didRestore.current true persistQueryClientRestore(options) .then(() refs.current.onSuccess?.()) .catch(() refs.current.onError?.()) .finally(() { setIsRestoring(false) }) } return isRestoring ? undefined : persistQueryClientSubscribe(options) }, [props.client, isRestoring]) return ( QueryClientProvider {...props} IsRestoringProvider value{isRestoring}{children}/IsRestoringProvider /QueryClientProvider )这段代码揭示了完整的信号时序组件挂载时isRestoring初始为true首次副作用触发persistQueryClientRestore(options)从 storage 中异步恢复被持久化的查询缓存在finally中把isRestoring置回false即恢复结束只有恢复结束后才会调用persistQueryClientSubscribe(options)订阅后续缓存变更以便后续把新查询继续写入持久化存储IsRestoringProvider用value{isRestoring}将这个状态包裹在整个QueryClientProvider子树之外。注意组件树结构IsRestoringProvider包裹在QueryClientProvider内部、children之外因此任何查询组件在读取 QueryClient 的同时都能感知恢复状态。PersistQueryClientProvider同时接受onSuccess/onError回调分别对应恢复成功与失败其中onSuccess的异步结果会在persistQueryClientRestoreresolve 后被等待。三、配套读取 HookuseIsRestoring要在自己的组件里感知恢复状态应当使用同文件导出的 Hookexport const useIsRestoring () useContext(IsRestoringContext)官方参考文档 useIsRestoring 给出的类型签名为function useIsRestoring(): boolean;返回值语义true持久化的查询客户端正在被恢复restore in progressfalse没有任何恢复流程在执行即默认状态。两个导出物IsRestoringProvider与useIsRestoring都在 preact-query/src/index.ts:56 从包的公共入口统一导出export { useIsRestoring, IsRestoringProvider } from ./IsRestoringProvider因此在应用中可以直接import { IsRestoringProvider, useIsRestoring } from tanstack/preact-query。四、内部消费useQuery如何用它规避竞态useIsRestoring不只是给开发者用——useQuery、useInfiniteQuery、useQueries等数据获取 Hook 自身也会读取它。以 useBaseQuery.ts:51 为例所有查询 Hook 的公共底座会执行const isRestoring useIsRestoring()随后它在下游产生了两个关键影响1. 控制乐观结果模式defaultedOptions._optimisticResults isRestoring ? isRestoring : optimistic当正在恢复时_optimisticResults被置为isRestoring查询的乐观结果在订阅外部存储前对QueryObserver结果做出的临时估算会进入恢复专用模式避免把尚未就绪的中间状态当作最终结果渲染。2. 抑制订阅直到恢复完成const shouldSubscribe !isRestoring options.subscribed ! false useSyncExternalStore( useCallback( (onStoreChange) { const unsubscribe shouldSubscribe ? observer.subscribe(notifyManager.batchCalls(onStoreChange)) : noop ...恢复期间shouldSubscribe为false观察者不订阅缓存变更退化为noop恢复结束后才真正开始订阅。这一机制的意义在于如果查询在恢复完成前就抢先发起 fetch 并写回缓存很可能覆盖掉刚从 storage 恢复出来的旧数据从而造成持久化失效或闪烁。恢复期静默挂起、恢复后订阅的设计正是对这种竞态的兜底。同样的模式也出现在多查询场景useQueries其实现同样位于 useQueries.ts内部会批量读取useIsRestoring()的状态来决定是否订阅与如何构造乐观结果并在tests/useQueries.test.tsx 与tests/useQuery.test.tsx 中有对应的测试覆盖PersistQueryClientProvider的集成行为则体现在 PersistQueryClientProvider.test.tsx。五、开发者侧的应用方式结合上述源码在实际 Preact 应用中的典型组合用法如下import { QueryClient } from tanstack/preact-query import { PersistQueryClientProvider } from tanstack/preact-query-persist-client import { createSyncStoragePersister } from tanstack/query-sync-storage-persister const queryClient new QueryClient() const persister createSyncStoragePersister({ storage: window.localStorage, }) export function App() { return ( PersistQueryClientProvider client{queryClient} persistOptions{{ persister }} onSuccess{() console.log(restore finished)} Main / /PersistQueryClientProvider ) }若需要在恢复完成前展示占位内容例如避免离线应用先渲染空态再突然跳出缓存数据可以直接读取信号import { useIsRestoring } from tanstack/preact-query function Main() { const isRestoring useIsRestoring() if (isRestoring) { return div正在恢复已保存的数据…/div } return TodoList / }这里useIsRestoring()读取的正是IsRestoringProvider提供的 Context 值值为true期间挂起渲染直到恢复完成值回到false后再渲染依赖缓存的 UI。由于恢复期间查询 Hook 本身不会发起多余的 fetch这一方案既能避免闪屏也不会产生与恢复流程竞争的请求。六、小结IsRestoringProvider是 IsRestoringProvider.ts 中导出的布尔型 Context Provider类型为Providerboolean默认值为false它由 PersistQueryClientProvider.tsx 驱动恢复开始时置truepersistQueryClientRestore结束后在finally中置回false配套的useIsRestoringHook见 useIsRestoring供开发者判断恢复状态底层useBaseQuery所有查询 Hook 的底座会自动读取该状态在恢复期以isRestoring模式计算乐观结果并抑制订阅从框架层规避恢复与挂载查询的竞态。因此理解IsRestoringProvider是理解 Preact Query 持久化能力tanstack/preact-query-persist-client配合tanstack/query-persist-client-core如何无痛衔接离线恢复与在线查询的钥匙——它不仅是暴露给外部的一个 Provider更是整个恢复流程与数据获取管线之间的协调中枢。【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/query创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门