本文正在参加「金石计划 . 瓜分6万现金大奖」
本文翻译自 TkDodo 的 Status Checks in React Query
React Query
的一个优势是可以简单获取 query
的状态,你可以立即知道 query
是在 loading 或者 它出错了,为此,该库暴露出来了一连串的 boolean
标识,其中大部分都来自于内部的状态机,查看这些类型,你的查询状态可以是以下之一
success
:你的query
是成功的,并且你拥有数据error
:你的query
没有成功,并且设置了一个错误loading
:你的query
当前没数据,并且是第一次加载idle
:你的query
还没有运行过,因为它未开启 (enable)
更新:idle
在 React Query
v4 中已经被删除
注意 isFetching
不是内部状态机的一部分,它是一个可选的标识,当正在请求时,它会为 true
,你可以同时处在 fetching
和 success
的状态,你可以同时处在 fetching
和 error
的状态,但是你不可能同时处在 success
和 loading
的状态,内部的状态机确保了这一点
更新:在 React Query
v4,isFetching
是从 fetchStatus
派生出来的,就比如 isPaused
,你可以从 #13: Offline React Query阅读更多
标准例子
idle
这里被排除在外,因为它是一个禁用的边缘例子,因此绝大多数例子看起来像这样
const todos = useTodos()
if (todos.isLoading) {
return 'Loading...'
}
if (todos.error) {
return 'An error has occurred: ' + todos.error.message
}
return <div>{todos.data.map(renderTodo)}</div>
我们首先检查了 loading
和 error
,然后展示了数据,这满足了大部分场景,但不是绝对的,很多数据请求的解决方案,特别是手写的,没有 refetching
机制,或者只有在用户触发时
但是 React Query
有,
默认情况下它的 refetching
是相当积极的,并且是在用户不主动触发的情况下,refetchOnMount
, refetchOnWindowFocus
和 refetchOnReconnect
这些概念对于保持数据准确性是相当好的。但是如果一个后台的 refetch
失败可能会造成混乱的用户体验
后台错误
在大多数情况下,后台获取数据失败,是可以忽略的,但是上面的代码没有这么做,我们可以看两个例子
-
用户打开了页面,然后初始化的
query
成功,他们在当前页面工作了一段时间,然后切换到了浏览器其它tab
检查了电子邮件,几分钟后他们回到了当前页面,React Query
会做后台的refetch
,现在请求失败了 -
用户打开了列表页面,然后点击一个其中一条进入了详情页面,之后他们返回了列表页面,一旦他们又再次进入了详情页面,他们将看到来此缓存的数据,这很棒 - 除非后台
refetch
失败
在这两种情况下 我们的查询都将处于以下的状态
{
"status": "error",
"error": { "message": "Something went wrong" },
"data": [{ ... }]
}
就像你看到的,我们有一个 error
和一个 陈旧的数据可用,这就是 React Query
的伟大之处,它使用了 stale-while-revalidate
缓存机制,这代表如果数据存在,它会始终给你,即使它是陈旧的
现在由我们来决定显示什么,显示错误重要吗?如果我们有陈旧的数据,只显示陈旧的数据够用吗?或者我们应该同时显示它们(添加一个错误的背景提示)
这个问题没有一个明确的答案,它去取决于你的使用场景,但是对于上面的两个例子,我觉得如果数据被替换成了错误,这将会是一个混乱的用户体验
当我们考虑到 React Query
会默认在失败时使用 指数退避
请求三次的时候这点就更重要了,因此可能会出现需要几秒钟才能将陈旧的数据变为错误页面,如果你也没有后台获取的提示,这可能会令人很困惑
这就是为什么我通常首先检查数据的可用性
const todos = useTodos()
if (todos.data) {
return <div>{todos.data.map(renderTodo)}</div>
}
if (todos.error) {
return 'An error has occurred: ' + todos.error.message
}
return 'Loading...'
同样,这里没有什么明确的原则说明这是对的,它高度依赖你的使用场景,每个人都应该意识到积极地重新获取所带来的的后果,并且构建相应的代码
本文正在参加「金石计划 . 瓜分6万现金大奖」