likes
comments
collection
share

React Query 快速入门

作者站长头像
站长
· 阅读数 20

很早之前就看到 React Query 在前端掘金圈子里火了一把,一直想学却因为种种原因没有开始。这一阵子闲下来了一些,快速学习了一下并且在自己的小项目里上手用了一番,体验非常不错。所以在这里以 React Query 为例写一篇 TanStack Query 小小的快速上手指南。

React Query

TanStack Query (FKA React Query) is often described as the missing data-fetching library for web applications, but in more technical terms, it makes fetching, caching, synchronizing and updating server state in your web applications a breeze.

TanStack Query(前称 React Query,在下文中我们也采用这个称呼)通常被形容为 Web 应用所缺失的数据请求库。更专业的说法是,他让你的 web 应用中的请求、缓存、同步与更新服务端状态更加轻而易举了。

从我这段时间的使用体验来看,其中对于请求与缓存的处理可以说是 React Query 给我带来的最显著的提升。

以这样一段请求为例👇🏻

function getListData() {
  return axios.get('https://xxxx');
}

function List() {
  // 数据
  const [data, setData] = useState([])
  // 加载状态
  const [loading, setLoading] = useState(false)
  // ...

  const queryData = () => {
    setLoading(true)
    getListData().then((res) => {
      // ...
      setData(res.data.data)
    }).catch((error) => {
      // ...
    }).finally(() => {
      setLoading(false)
    })
  }

  useEffect(() => {
    // 满足某种条件才请求
    if (fulfilled) {
      queryData();
    }
  }, [])

  // ...
  // return template;
}

使用 React Query 管理请求后,我们可以这样写(用过 ahooks 的 useRequest 的小伙伴应该很熟悉这种写法)

function List() {
  // ...
  const { data, isFetching } = useQuery({
    queryFn: getListData, // 查询函数
    queryKey: ["list", "query"], // 查询键
    enabled: fulfilled, // 是否启用
  });

  // ...
  // return template;
}

在外层,我们需要创建一个 QueryClient 并使用 QueryClientProvider 来提供一个查询的上下文。

const queryClient = new QueryClient()

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

我们把冗长的请求逻辑全部都交由 React Query 来帮我们处理,我们只需要关心请求的状态和数据即可。

更详细一些

让我们聚焦在例子中 useQuery 这个方法上

const { data, isFetching } = useQuery({
  queryFn: getListData, // 查询函数
  queryKey: ["list", "query"], // 查询键
  enabled: fulfilled, // 是否启用
});

入参

对于入参,这里我们就需要介绍一下 React Query 中最关键的两个参数:queryFnqueryKey

查询函数(queryFn)需要是能够返回 Promise 的任意函数。而该 Promise 的返回值将会被填充至 useQuery 返回的 结果数据 data 或是 错误 error

查询键(queryKey)需要是一个数组,其元素可以是任何可以被序列化的类型。

当然, React作为一个开箱即用的库,其本身还包含着一些默认配置。如果你发现 Devtool 的网络 tab 中时不时冒出来一个预期意外的请求。不要着急提Bug,这可能是以下几个默认开启的配置项在“搞鬼”。

  • refetchOnMount:在组件挂载时自动请求
  • refetchOnWindowFocus:在页面被重新focus时自动请求
  • refetchOnReconnect:网络重新连接时自动请求

除此之外,还有一种配置会导致重复的请求行为。不过这个需要手动开启,一般不会在开发者不知情的情况下触发请求。

  • refetchInterval:定时请求

对于那些默认的配置,你可以通过在 useQuery 的入参中关闭他们,或者在创建 queryClient 的时候就将他们全局关闭。

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      refetchOnReconnect: false,
      refetchOnWindowFocus: false,
      // ...
    },
  },
});

返回

对于 useQuery 返回的结果,一翻文档发现有25个属性

const {
	data,
	dataUpdatedAt,
	error,
	errorUpdateCount,
	errorUpdatedAt,
	failureCount,
	failureReason,
	fetchStatus,
	isError,
	isFetched,
	isFetchedAfterMount,
	isFetching,
	isInitialLoading,
	isLoading,
	isLoadingError,
	isPaused,
	isPlaceholderData,
	isPreviousData,
	isRefetchError,
	isRefetching,
	isStale,
	isSuccess,
	refetch,
	remove,
	status
} = useQuery(options);

大多数变量都可以见名知意,但是有一些细心的小伙伴可能发现了,这里的状态有非常多种,看起来貌似非常复杂。别急,让我们细细梳理一番。

在 React Query 中,我们有两个独立的状态 fetchStatusstatus ,分别对应请求本身的状态和结果的状态。什么意思嘞?

请求本身的状态 fetchStatus ,也就是指我们的请求函数 queryFn 的状态,它在执行还是在摸鱼?useQuery 给了我们以下几种状态。当 fetchStatus 为 xx 时,

  1. fetching:该请求函数正在卖力干活!对应 isFetching
  2. pause:请求函数本应干活,但是因为网络等原因被迫暂停了。对应 isPause
  3. idle:该请求函数正在卖力摸鱼(空闲)!对应 isIdle

status 则是对结果 data 的状态描述,我的数据是一个什么样的状态?当 status 为 xx 时,

  1. loading:你先别急,还没数据。对应 isLoading
  2. error:你的数据遇到了点错误,具体信息可以看看返回值中的error。对应 isError
  3. success:你的数据安全获取到了,存在 data 里啦。对应 isSuccess

这些状态一般来说就足以支撑我们绝大多数的场景了。

关于查询键

其实了解了上面的内容,已经可以开始上手开发了。不过对于查询键,咱还是想要多说两句。React Query 作为一个请求管理库,核心就是要将不同的请求统一管理。而对于不同的请求,React Query 通过唯一的 queryKey 来进行标识分组

举个🌰,对于这些个 query

const queryA = useQuery(["a1", "b1", "c1"], queryFnA);
const queryB = useQuery(["a1", "b1", "c2"], queryFnB);
const queryC = useQuery(["a1", "b2", "c1"], queryFnC);
const queryD = useQuery(["a2", "b1", "c1"], queryFnD);

你可以想象成 React Query 维护了这样的一个集合

React Query 快速入门

在未来,我们需要用 React Query 的更高级的功能时,特别是对一些特定的 query 进行操作时,我们只需要通过 queryKey 就可以轻松查找到我们想要的 query 了。

例如我需要找出 queryA 和 queryB ,那么我就可以通过 ["a1", "b1"] 来筛选得到想要的结果。

所以,在设计或者编写 queryKey 的时候,建议“三思而后行”。

最后

到这里,这篇小小的指南也要走到尽头了,但 React Query 才刚刚开始,在本文中,我们只讨论了最基础的查询,如果你想实现更多场景,例如分页,无限滚动等。亦或是向服务端发送删除,更新一类的请求(useMutation)。还是需要在文档中继续学习一番。

这里还推荐一下修仙大橙子dalao的专栏,也可以配合文档食用~

在阅读 React Query 的文档时,我发现了这样一段话

Out of the box, TanStack Query is configured with aggressive but sane defaults. Sometimes these defaults can catch new users off guard or make learning/debugging difficult if they are unknown by the user.

TanStack 是开箱即用的,使用了一套侵入性但健全的出厂配置。如果不知道这些出厂配置的话,可能会使新用户猝不及防,或是让他们的学习和debug变得困难。

想到我很早之前想学习 React Query 的时候,也是受到了某些“坑”的影响,转身干别的事去了(不可取不可取)。我希望在读完这篇小小的指南后,可以帮助你们平缓地度过这一段陡坡~

转载自:https://juejin.cn/post/7246055010187051045
评论
请登录