react-query

爱亮
2023-12-01

修仙大橙子:https://segmentfault.com/a/1190000041939135

查询键(Query Keys)及查询函数(Query Functions)

const getMenuId = () =>
	request<{ id: string; name: string }>({
	  url: `/menu`,
	  method: "GET",
	});
	
const query = useQuery(["getMenuIdByName"], async () => getMenuId());
  • 其中["getMenuIdByName"] 就是react-query的查询键,react-query通过不同的查询键来标识(映射)不同接口(或是同一接口不同参数请求)返回的数据。在react-query@4中,查询键必须是数组。
  • getMenuId()就是查询函数。
  • 为了方便记忆,打个比方,你可以将查询键看做是你存储localStorage时的key,而value则是通过查询函数查询到数据后,将各种我们需要的状态数据存储进入value

查询键常见问题

查询键的值不能重复,需要保持唯一

  • 如果查询键相同时,后面请求的数据会覆盖前面请求的数据!解决这个问题的办法是:可以在数组的第一个元素中,放一个字符串来标识当前的数据类型,就可以解决这个问题。
  • 在查询键变化时(包括对象内的变化,react-query将会进行深度比较),react-query将会重新调用查询函数
const usersQuery = useQuery( ['users', userId], fun);

查询函数

  • 查询函数可以是任何Promise函数,包括但不局限于fetch、axios、graphql请求、异步浏览器api等。

并行请求

  • 前端请求后端接口时,通常会请求多个接口。如果要等到所有数据返回后,才给用户显示内容。此时就需要使用Promise.all(用react-query以前)来合并请求。
  • useQueries钩子接受一个带有查询键的选项对象,其值是一个数组,其中查询选项对象与useQuery钩子相同(不包括context选项)。
  • 该useQueries钩子返回一个包含所有查询结果的数组。
const [users, setUsers] = React.useState([
    'facebook',
    'vuejs',
    'nestjs',
    'mongodb',
  ]);

const getRepos = (username) =>
  fetch(`https://api.github.com/users/${username}/repos`).then((res) =>
    res.json()
  );

const userQueries = useQueries({
  queries: users.map((user) => {
    return {
      queryKey: ['user', user],
      queryFn: () => getRepos(user),
    };
  }),
});

依赖请求

请求B接口的某个参数依赖A接口请求返回的内容

  • query.fetchStatusfetchStatus一共有三个状态,fetching状态表示当前查询函数正在运行idle状态表示当时查询函数不在运行paused状态表示查询函数尝试运行,但是无法进行请求,最可能的原因是由于当前没有联网,处于离线状态
  • fetchStatus将会在idle、fetching、paused这三个状态间经历循环。
  • isLoadingtrue表示第一次请求未返回结果前这段时间的状态,如果对接口进行了禁用(通过enabled来控制),可以通过fetchStatusidle来获取接口禁用请求这段时间的状态。
// labels为上一个请求的data
const query = useQuery(["getMenuIdByName"], async () => getMenuId(), {enabled: !!labels});

缓存状态

react-query获取数据的过程中,主要会经历以下三种状态:loading、error、success

  • react-query是否会触发查询函数,并从后端接口获取数据,与缓存状态是:fresh(最新)状态或stale(老旧)状态有关。如果缓存状态是stale(老旧),表示该查询将会有资格重新获取,但如果缓存状态是fresh(最新)的,就不会重新获取。
  • 将配置中的staleTime,设置一个毫秒数的数字,那么缓存将会在staleTime毫秒后过期(从fresh(最新)变为stale(陈旧))
  • staleTime设置为Infinity,表示当前查询的数据将只会获取一次,且会在整个网页的生命周期内缓存。

触发重新获取数据的条件

  1. 组件挂载时
    当组件首次加载,将会触发数据的获取。如果组件被卸载后再次被加载,此时也会触发数据的重新获取。
  2. 查询键改变时
    当查询键改变时,将会自动触发数据的重新获取。如果你的查询键中有对象,也不要担心react-query无法检测出来变化,因为react-query会进行深度比对。
  3. 页面重新被聚焦
    和小程序的onShow生命周期类似,触发就会重新获取数据,需要此时在stale状态。这个触发条件是默认开启的,如果希望关闭这个触发条件,可以把refetchOnWindowFocus选项设置为false来禁止。
  4. 网络重新连接
    这个触发条件同样是默认开启的。如果希望关闭这个触发条件,可以把refetchOnReconnect选项设置为false来禁止。
  5. 定时刷新
    这是一个需要你自己配置的一个触发条件。当你在配置中设置refetchInterval为数字(代表xxx毫秒)时。无论此时数据是fresh(最新)还是stale(老旧)的缓存状态,react-query都会在你设置的毫秒时间间隔内重新获取数据。

注意:除了定时刷新外,其它的触发器,都需要状态是stale(陈旧)才可以触发。

清理缓存

  • 在缓存状态处于inactive(不活跃)状态或者使用这个查询数据的组件卸载时,超过5分钟(默认情况下)后,react-query将会自动清除该缓存。
  • 如果你希望自定义这个时间,你可以使用cacheTime配置,下面的例子中将cacheTime设置为0,实现的效果是,当查询数据在inactive状态时,立即从缓存中删除。
const userQuery = useQuery(
  ["user", username],
  () =>
    fetch(`https://api.github.com/users/${username}`)
    .then(res => res.json()),
  { cacheTime: 0 }
);
 类似资料: