服务端状态管理的解决方案:React Query
date
Dec 10, 2020
slug
react-query
status
Published
tags
React
State Management
summary
type
Post
React Query 是什么?
客户端应用的状态可以分为两类:
- 客户端状态 Client State:多数用于控制客户端的 UI 展示,存在于客户端。
- 服务端状态 Server State:客户端通过异步请求获得的数据,存在于服务端。
React Query 是适用于在客户端管理服务端状态的库。
React Query 解决了什么问题
服务端状态有以下特点:
- 存储在远端,本地无法直接控制
- 需要异步 API 来查询和更新
- 可能在不知情的情况下,被另一个请求方更改了数据,导致数据不同步
现有的状态管理库(如 Mobx、Redux等)适用于管理客户端状态,但它们并不关心客户端是如何异步请求远端数据的,所以他们并不适合处理异步的、来自服务端的状态。
而 React Query 就是为了解决服务端状态带来的上述问题而出现的,除此之外它还带来了以下特性:
- 更方便地控制缓存
- 把对于相同数据的多个请求简化成一个
- 在后台更新过期数据
- 知道数据什么时候会「过期」
- 对于数据的变化尽可能快得做出响应
- 分页查询和懒加载等请求性能优化
- 管理服务器状态的内存和垃圾回收
- 通过结构共享(structural sharing)来缓存查询结果
简单实用示例
function Todos() {
const { isLoading, isError, data, error } = useQuery('todos', fetchTodoList)
if (isLoading) {
return <span>Loading...</span>
}
if (isError) {
return <span>Error: {error.message}</span>
}
// also status === 'success', but "else" logic works, too
return (
<ul>
{data.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
)
}
作为一个状态管理库,它怎么解决 props drilling 问题?
我们知道传统的状态管理库所解决的痛点之一就是 props drilling。React Query 对这个问题的解决方案有别于其他库,它是通过 stale-while-revalidate 内存缓存来解决的。
使用 React Query 中的每一个 useQuery 都会创建一个实例,同一页面中对于相同的请求的多个实例,useQuery 只会发起一次请求。第一次 useQuery 请求的数据会被存入内存缓存,后续的调用都会直接从缓存中拿取数据。所以在组件组建中调用 useQuery 即可解决 props drilling 等问题。
在组件 unmount 之后,当在一定时间内(默认为 5 分钟)没有再发现示例的出现,那么这个请求及其响应数据就会被回收。
具体可查看 React Query 的缓存策略。
参考资料