百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

React-Query:解锁你的应用程序潜力,轻松解决接口请求难题!

zzlvtu 2024-09-04 23:00 7 浏览

前言

如果你平常会写前后端交互的react页面,那你一定写过这样的代码.

 function App() {
 
   const [data, updateData] = useState(null);
   const [isError, setError] = useState(false);
   const [isLoading, setLoading] = useState(false);
   
   useEffect(async () => {
     setError(false);
     setLoading(true);
     try {
       const data = await axios.get('/api/user');
       updateData(data);
     } catch(e) {
       setError(true);
     }
     setLoading(false);
   }, [])
    
   if(isLoading) return ...
   
   if(isError) return ...
   
   return <List users={data}/>
 }
 

这是一个组件拉取服务端数据的简单例子,在组件中,我们简单拉取了一个接口的数据,并监听接口的状态,根据状态来更新不同的UI。

如果有性能上的要求,那这里可能还需要加上一段缓存的逻辑

 //...
     try {
 +      if(sessionUtil.get('users'){
 +          updateData(sessionUtil.get('users'));
 +          return;
 +      }
       const data = await axios.get('/api/user');
 +     sessionUtil.set('users',data)
       updateData(data);
     } catch(e) {
       setError(true);
     }
 //...

至此,这个组件已经变得相当复杂了,如果组件拉取了好几个接口,那么这一套逻辑还得写好几遍。

1 一些状态管理库的弊端

许多状态管理库,比如redux,可以很流畅的管理页面的状态,也有处理副作用的能力,但往往不能很好的处理服务端的状态,因为处理服务端的状态,通常还包括:

  • 缓存
  • 将对同一数据的多个请求消除为一个请求
  • 在后台更新“过期”数据
  • 知道数据何时“过期”
  • 尽快反映数据更新
  • 性能优化,如分页和延迟加载数据
  • 管理内存和服务器状态的垃圾收集
  • 使用结构共享记忆查询结果

直到React-Query的出现,上面的问题都变得迎刃而解。

2 React-Query

React Query 是一个开箱即用,零配置的服务端状态管理库,支持RestfulGraphQL两种类型的请求,它能帮助你很好的获取、同步、管理和缓存你的远程数据。它提供了几个简单的Hooks,借助它们可以很轻松的完成对后端数据的增删改查等操作,无需再写繁琐的数据拉取和状态判断等代码。

React-Query的官方文档没有大纲,阅读起来相当不方便,个人感觉,直接阅读github源码项目中的docs要更方便一些。链接地址:https://github.com/TanStack/query/tree/main/docs/react

2.1 简单使用

2.1.1 QueryClientProvider

首先,需要在组件外层定义一个queryClient作为组件操作和使用数据的一个共同容器,通过QueryClientProvider组件注入到项目中。

 import {
   QueryClient,
   QueryClientProvider,
   useQuery,
 } from '@tanstack/react-query'
 
 const queryClient = new QueryClient()
 
 export default function App() {
   return (
     <QueryClientProvider client={queryClient}>
       <Example />
     </QueryClientProvider>
   )
 }

在创建QueryClient的时候,我们可以传入一些参数,用于管理项目中的请求、缓存、日志的相关配置,这些配置会对整个项目生效,其中包含了四个模块的配置参数。

 new QueryClient({
   queryCache?: QueryCache;
   mutationCache?: MutationCache;
   logger?: Logger;
   defaultOptions?: DefaultOptions;
 })
  • queryCache: 请求缓存相关配置
  • mutationCache: 数据修改缓存相关配置
  • logger: 日志相关配置
  • defaultOptions:请求基础配置

其中defaultOptions用于配置项目中useQuery请求的管理,常用的配置如下:

  • staleTime: 重新获取数据的时间间隔 默认0
  • cacheTime: 数据缓存时间 默认 1000 60 5 5分钟
  • retry: 失败重试次数 默认 3次
  • refetchOnWindowFocus: 窗口重新获得焦点时重新获取数据 默认 false
  • refetchOnReconnect: 网络重新链接
  • refetchOnMount: 实例重新挂载时重新拉取请求
  • enabled: 如果为“false”,“useQuery”不会触发,需要使用其返回的“refetch”来触发操作
  • queryFn:全局定义请求方法,其他地方使用时只需要直接传入请求参数

2.1.2 useQuery

useQueryReact-Query提供的用于请求接口并管理请求状态等信息的Hook。

例如:

 function Example() {
   const { isLoading, error, data } = useQuery({
     queryKey: ['repoData'],
     queryFn: () =>
       fetch('https://api.github.com/repos/TanStack/query').then(
         (res) => res.json(),
       ),
   })
 
   if (isLoading) return 'Loading...'
 
   if (error) return 'An error has occurred: ' + error.message
 
   return (
     <div>
       <h1>{data.name}</h1>
       <p>{data.description}</p>
       <strong> {data.subscribers_count}</strong>{' '}
       <strong>? {data.stargazers_count}</strong>{' '}
       <strong> {data.forks_count}</strong>
     </div>
   )
 }

userQuery接收一个配置对象,其中

  • queryKey:必传,用作请求数据缓存的唯一key值,也可以在数组中,写入多项如:['repoData', '1'],这样React-Query在使用的时候会自动把它拼接为/repoData/1,这个在缓存用户访问过的页面时,非常有用。
  • queryFn:用于请求的方法,如果在QueryClient中配置了,这里可以不必再写,需要返回请求完成后所处理的数据。

除了这两项基本的参数,useQuery还可以传入上面defaultOptions的所有参数,来表示对这个请求单独的配置。

然后useQuery会返回一个对象,里面包含着请求相关的所有信息,这些信息会随着请求的进度而改变,就无须我们再使用一组state变量来进行管理了,常用的包括:

  • isLoading:请求是否正在进行
  • error:请求是否出错,这里只会对500404等做出反应,如果有其他情况错误情况,需要在请求方法里面throw
  • isSuccess: 请求是否成功
  • status: 请求状态,包含上面几种情况
  • data:返回数据

除此之外,使用useQuery拉取回来的数据,会被默认缓存起来,然后可以通过配置过期时间,重新拉取等策略来进行管理。

2.1.3 useQueryClient

通过useQueryClient,我们可以获取到之前注入的容器实例,里面保存着所有我们缓存的信息,以及配置信息,而它本质上其实也是对React.useContext的封装。

以上面Example组件为例,如果我们想在另一个组件访问这些数据。

 function Example() {
   const queryClient = useQueryClient()
 
   const data = queryClient.getQueryData(['repoData'])
 
   return (
     //...
   )
 }

除了访问缓存数据,queryClient还有很多API:

  • queryClient.fetchQuery
  • queryClient.fetchInfiniteQuery
  • queryClient.prefetchQuery
  • queryClient.prefetchInfiniteQuery
  • queryClient.getQueryData
  • queryClient.refetchQueries
  • queryClient.cancelQueries
  • queryClient.removeQueries
  • queryClient.resetQueries
  • ...

大家可以根据需要去官网查阅。

2.1.4 useMutation

除了获取数据,很多时候还需要处理数据的修改,比如说最简单的todo list例子,除了拉取数据列表,还需要增删改数据,而这个时候除了需要发送接口,还需要修改本地的数据,React-Query提供了useMutation来帮我们完成这些事情。

以上面Example组件为例,我们已经拉取到了data,现在我们想新增一条数据,那我们可以

 const {isLoading,isError,isSuccess,mutate} = useMutation({
     mutationFn: async (newData) => insertNewData(newData),
     onSuccess: () => {
       queryClient.invalidateQueries({ queryKey: ['repoData'] });
     },
     onError: (error) => {
       console.log(error)
     }
   });

这里我们传入了:

  • mutationFn:代表元数据的方法
  • onSuccess:接口调用成功后的回调
  • onError: 失败的回调

返回的数据和useQuery基本是相同的,这里的mutate则是触发更改的方法,如果我们想执行useMutation中传入的方法,我们只需要调用mutate即可,传给mutate的参数都会被带到useMutation的构造方法中。

   const updateData = async (newData) => {
     mutate(newData);
   };

以上就是React-Query最核心的对服务端数据进行增删改查的功能,除此之外,React-Query还有很多其他的能力。

2.2 数据预获取

有时候我们不需要整个页面loading来等待数据加载,我们更希望在用户操作之前就拉取完数据,比如用户hover详情链接,而不是点击详情的时候。

那我们可以使用queryClientprefetchQuery方法,提前拉取到用户可能会访问的数据,并加入到缓存中,由于不需要监听服务端状态等,所以这个方法会比useQuery高效许多。

onMouseEnter={async () => {
  await queryClient.prefetchQuery({
    queryKey: ['character', char.id],
    queryFn: () => getCharacter(char.id),
    staleTime: 10 * 1000, // only prefetch if older than 10 seconds
  })
}}

2.3 分页缓存

通过动态设置queryKey,并将keepPreviousData设置为true,我们可以很轻松的缓存之前页码的数据

  const { status, data, error, isFetching, isPreviousData } = useQuery({
    queryKey: ['projects', page],
    queryFn: () => fetchProjects(page),
    keepPreviousData: true,
    staleTime: 5000,
  })

2.4 滚动列表渲染

使用useInfiniteQuery定义拉取数据的方法,以及上下页的逻辑,然后会返回更新页面数据的状态,以及触发更新的方法。

  const {
    status,
    data,
    error,
    isFetching,
    isFetchingNextPage,
    isFetchingPreviousPage,
    fetchNextPage,
    fetchPreviousPage,
    hasNextPage,
    hasPreviousPage,
  } = useInfiniteQuery(
    ['projects'],
    async ({ pageParam = 0 }) => {
      const res = await axios.get('/api/projects?cursor=' + pageParam)
      return res.data
    },
    {
      getPreviousPageParam: (firstPage) => firstPage.previousId ?? undefined,
      getNextPageParam: (lastPage) => lastPage.nextId ?? undefined,
    },
  )

2.5 devTools配套开发工具

导入开发工具

import { ReactQueryDevtools } from 'react-query/devtools'

<ReactQueryDevtools initialIsOpen={false} />

默认情况下,当process.env.NODE ENV === 'production' 时开启 Devtools ,不必担心构建时需要排除他们

浮动模式下开启,会将devtools作为固定的浮动元素安装在开发的应用程序中,并在屏幕一角提供一个切换按钮以显示和隐藏devtools

在devtools中我们可以直观的看到已经缓存下来的数据和整个项目的配置,以及各个接口的状态等。


3 总结

感谢你能看到这里,本文简单介绍了React-Query对服务端数据进行增删改查的功能实现,以及React-Query的一些其他能力,希望对你有用,React-Query的使用场景没有其他状态管理库那么广泛,但还是能解决很多服务器拉取数据的痛点。

相关推荐

什么是DPDK?DPDK的原理及学习学习路线总结

一、什么是DPDK  对于用户来说,它可能是一个性能出色的包数据处理加速软件库;对于开发者来说,它可能是一个实践包处理新想法的创新工场;对于性能调优者来说,它可能又是一个绝佳的成果分享平台。 ...

每天进步一点:两分钟解决kvm下windows虚拟机鼠标不跟随

跟随昨天文章做测试的朋友们应该和我一样遇到了vnc连接windows鼠标不跟随的问题,经过一番查找有两种解决办法:1.编辑配置文件命令virshedittest或者直接vi/etc/libvir...

PC虚拟化主流:KVM、XEN、OpenVZ详解

目前,PC的虚拟化逐渐成为互联网发展的大趋势,我们知道,KVM、XEN、OpenVZ是虚拟化的三种方式,今天我们就来探讨这三种虚拟化的优势和劣势。1、pc虚拟化——KVMKVM是完整的硬件虚拟化,可在...

Windows上使用QEMU创建aarch64(ARM64)虚拟机

前言随着国产化的推进,现在采用ARM、MIPS的机器越来越多,作为开发、运维人员要调测软件总不能每种架构的机器都去买一台吧?主要像博主这样的穷B,实在也是承受不起。。需要的工具...

高度致敬Windows!开源优麒麟20.04 LTS发布:支持5年

优麒麟团队宣布,优麒麟(UbuntuKylin)开源操作系统20.04LTS正式版已经发布,代号FocalFossa,全球同步发布的还有Ubuntu20.04、Lubuntu20.04、Xub...

极空间虚拟机上线了,一学就会!小白保姆级使用教程

友情提示本文涉及内容较多,篇幅在4500字左右,为了对小白用户更加友好,图片示例多达60张。整个文章部分为三个阶段,准备-初探-实战。其中实战部分包含Windows系统,ikuai软路由系统,iSto...

Windows Subsystem for Linux现以应用形式上架Microsoft Store

微软今天宣布WindowsSubsystemforLinux(WSL)作为一款应用上架Windows11端的MicrosoftStore。也就是说,现在WSL以应用的方式通过...

Windows Server 2019 Core 虚拟机系统镜像制作

WindowsServer2019Core简介WindowsServer2019是微软于2018年11月13日发布的新一代WindowsServer服务器操作系统,基于Win10180...

微软商店中的WSL预览版现已可用!Windows 11用户狂喜

...

在NAS上安装Win10,24小时待命的云电脑达成√

#头条创作挑战赛#引子...

免费开源虚拟机VirtualBox 7.0.12发布:修复TPM和黑屏问题

IT之家10月18日消息,甲骨文近日发布了VirtualBox7.0.12维护版本更新,重点修复此前版本中用户反馈和官方发现的BUG,改善了对LinuxKernel6.4/6.5...

KVM Cloud 虚拟机管理系统安装部署

KVMCloud介绍KVMCloud是一款基于KVM实现的适用于小微企业的虚拟机管理系统,支持如下功能:基于KVM的VM基础功能(创建、启动、停止、重装、webVNC等功能)使用NFS作为磁盘...

个人KVM 虚拟化学习笔记(kvm虚拟化管理平台)

一、KVM原理二、KVM基础功能2.1CPU2.2内存2.3存储2.4网络三、KVM高级功能...

kvm虚拟化之ESXi到KVM之v2v迁移(esxi虚拟机迁移到另一个esxi)

1.ESXi到KVM之v2v情况说明(1).配置任务列表:1)VMwareESXi虚拟平台下linux系统迁移到KVM虚拟平台。2)VMwareESXi虚拟平台下windows系统迁移到KVM虚拟平台...

unraid下虚拟机安装Windows(vmware安装unraid)

unraid下虚拟机安装Windows使用unraid也有一段时间了,主要是做数据备份,以及docker容器的安装测试,今天有空测试一下VMS虚拟机的使用,用在unraid上安装windows7操作系...