React-Query源码探秘 2-QueryClient

877 阅读1分钟

专栏目录: 全网最细 React-Query源码探秘 - 不月阳九的专栏 - 掘金 (juejin.cn)

QueryClient是React-Query的上层类,一般开发者不会直接访问Query对象,而是通过QueryClient类或者useQuery钩子去进行访问。

我们来看一下官网的使用说明

我们需要将client通过context的Provider共享给App下所有的组件才能正常使用React-Query

const client = new QueryClient()

return (
    <QueryClientProvider client={client}>
        <App/>
    </QueryClientProvider> 
)

源码中QueryClient通过React.context进行管理 让其可以被分发

const queryClient = React.useContext(
    getQueryClientContext(React.useContext(QueryClientSharingContext))
  )

源码解析

QueryClient提供了三种请求

image.png

fetch请求

prefetchQuery预请求

在useQuery使用数据之前,提前获取想要的数据,当真正用数据时,就可以从QueryCache获取缓存的Query对象上的数据

invalidateQueries主动失效

当开发者已明确知道Query data已经变更(不是新鲜的),可以调用invalidateQueries让对应的Query变成失效状态,同时重新请求网络数据

export class QueryClient {
    constructor(){...}
    
    // fetchQuery方法  会创建/找到一个Query,判断数据是否在新鲜时间内(isStale)
    // 如果数据不新鲜调用query.fetch方法,发起网络请求
    // 如果数据新鲜,则直接返回Query上的缓存数据
    fetchQuery(options){
        ...
        const query = this.queryCache.build(this, defaultedOptions)
        return query.isStaleByTime(defaultedOptions.staleTime)
        ? query.fetch(defaultedOptions)
        : Promise.resolve(query.state.data)
    }
    
     // 实际上调用的是 fetchQuery 
     // 但是之后使用noop(空函数)进行处理  不会抛出错误也不会刷新页面 
     // 用户使用的时候才会正常获取数据
    preFetchQuery(){
        ...
       return this.fetchQuery(arg1 as any, arg2 as any, arg3)
      .then(noop)
      .catch(noop)
    }
    
    // 将cache中的所有Query都invalidate失效
    // 之后重新refetchQueries
    invalidateQuery(){
        ...
        this.queryCache.findAll(filters).forEach((query) => {
        query.invalidate()
        })
        return this.refetchQueries(refetchFilters, options)
    }
}