修仙大橙子: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.fetchStatus
:fetchStatus
一共有三个状态,fetching
状态表示当前查询函数正在运行,idle
状态表示当时查询函数不在运行。paused
状态表示查询函数尝试运行,但是无法进行请求,最可能的原因是由于当前没有联网,处于离线状态。fetchStatus
将会在idle、fetching、paused
这三个状态间经历循环。isLoading
为true
表示第一次请求未返回结果前这段时间的状态,如果对接口进行了禁用(通过enabled
来控制),可以通过fetchStatus
为idle
来获取接口禁用请求这段时间的状态。
// 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
,表示当前查询的数据将只会获取一次,且会在整个网页的生命周期内缓存。
触发重新获取数据的条件
- 组件挂载时
当组件首次加载,将会触发数据的获取。如果组件被卸载后再次被加载,此时也会触发数据的重新获取。 - 查询键改变时
当查询键改变时,将会自动触发数据的重新获取。如果你的查询键中有对象,也不要担心react-query
无法检测出来变化,因为react-query
会进行深度比对。 - 页面重新被聚焦
和小程序的onShow
生命周期类似,触发就会重新获取数据,需要此时在stale
状态。这个触发条件是默认开启的,如果希望关闭这个触发条件,可以把refetchOnWindowFocus
选项设置为false
来禁止。 - 网络重新连接
这个触发条件同样是默认开启的。如果希望关闭这个触发条件,可以把refetchOnReconnect
选项设置为false
来禁止。 - 定时刷新
这是一个需要你自己配置的一个触发条件。当你在配置中设置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 }
);