服务端状态管理的解决方案:React Query

date
Dec 10, 2020
slug
react-query
status
Published
tags
React
State Management
summary
type
Post

React Query 是什么?

客户端应用的状态可以分为两类:
  1. 客户端状态 Client State:多数用于控制客户端的 UI 展示,存在于客户端。
  1. 服务端状态 Server State:客户端通过异步请求获得的数据,存在于服务端。
React Query 是适用于在客户端管理服务端状态的库。

React Query 解决了什么问题

服务端状态有以下特点:
  1. 存储在远端,本地无法直接控制
  1. 需要异步 API 来查询和更新
  1. 可能在不知情的情况下,被另一个请求方更改了数据,导致数据不同步
现有的状态管理库(如 Mobx、Redux等)适用于管理客户端状态,但它们并不关心客户端是如何异步请求远端数据的,所以他们并不适合处理异步的、来自服务端的状态。
而 React Query 就是为了解决服务端状态带来的上述问题而出现的,除此之外它还带来了以下特性:
  1. 更方便地控制缓存
  1. 把对于相同数据的多个请求简化成一个
  1. 在后台更新过期数据
  1. 知道数据什么时候会「过期」
  1. 对于数据的变化尽可能快得做出响应
  1. 分页查询和懒加载等请求性能优化
  1. 管理服务器状态的内存和垃圾回收
  1. 通过结构共享(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 的缓存策略。

参考资料

© Sytone 2021