react-query的介绍和使用

12 篇文章 0 订阅

一、 react-query介绍

1.1 react-query是什么

react-query是一个异步状态管理的hook,内置了loading,error等状态。

1.2 react-query的作用

  • 封装了loading、error等方便使用,减少代码量
  • 多个组件请求同一个query时只发送一个请求
  • 缓存更新和时效策略

1.3 react-query和redux的区别

react-query和redux都能进行状态管理和异步数据的处理,react-query更偏向于服务器之间的异步数据的管理

1.4、概览

没使用react-query之前,你的代码可能是这样的

import { useEffect, useState, useMemo, memo } from 'react';

const fetchList = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const list = [
        { id: '1', name: 'banana' },
        { id: '2', name: 'orange' },
        { id: '3', name: 'apple' },
        { id: '4', name: 'strawberry' },
        { id: '5', name: 'grape' },
      ];
      resolve({ data: list })
    }, 1000);
  });
};

function List() {
  const [list, setList] = useState([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    setLoading(true);
    fetchList().then(res => {
      setLoading(false);
      setList(res?.data)
    }).catch(err => setLoading(false))
  }, []);

  const renderList = useMemo(() => {
    return list.map(l => <div key={l.id}>
     {l.name}
    </div>);
  }, [list]);

  return (
    <div className='list'>
      {loading ? 'loading' : renderList}
    </div>
  );
}

function App(){
  return <div className='app'>
     <List/>
  </div>
};

export default memo(App);

使用react-query

import { memo } from 'react';
import { useQuery, QueryClientProvider, QueryClient } from 'react-query';

const fetchList = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const list = [
        { id: '1', name: 'banana' },
        { id: '2', name: 'orange' },
        { id: '3', name: 'apple' },
        { id: '4', name: 'strawberry' },
        { id: '5', name: 'grape' },
      ];
      resolve({ data: list })
    }, 1000);
  });
};


function List() {

  const { isLoading, error, data } = useQuery('getListData', () => fetchList().then(res => res.data));

  if (error) {
    return 'An error has occurred: ' + error.message
  }

  if (isLoading) {
    return 'data is loading.'
  }

  return data.map(l => <div key={l.id}>
    {l.name}
  </div>);
}


function App() {
  const queryClient = new QueryClient();
  return <div className='app'>
    <QueryClientProvider client={queryClient}>
      <List />
    </QueryClientProvider>
  </div>
};

export default memo(App);

多个组件请求同一个query只会进行一次请求

function List() {

  const { isLoading, error, data } = useQuery('getListData', () => fetchList().then(res => res.data));

  if (error) {
    return 'An error has occurred: ' + error.message
  }

  if (isLoading) {
    return 'data is loading.'
  }

  return data.map(l => <div key={l.id}>
    {l.name}
  </div>);
}

function List1() {

  const { isLoading, error, data } = useQuery('getListData', () => fetchList().then(res => res.data));

  if (error) {
    return 'An error has occurred: ' + error.message
  }

  if (isLoading) {
    return 'data is loading.'
  }

  return data.map(l => <div key={l.id}>
    {l.name}
  </div>);
}


function App() {
  const queryClient = new QueryClient();
  return <div className='app'>
    <QueryClientProvider client={queryClient}>
      <List />
      <List1/>
      <ReactQueryDevtools initialIsOpen={false} position='top-right'/>
    </QueryClientProvider>
  </div>

List和List1都使用了getListData这个query,但最终只会请求一次

二、基础使用

2.1 useQuery

useQuery接收两个参数,第一个是唯一表示key,第二个是一个fetch的异步函数。key是一个唯一的字符串,用来标识query,key还可以是个数组,存放query依赖的一些变量,类似于useMemo和useCallback,当依赖发生变化时会重新发起请求

  const [id, setId] = useState(0)

  const { isLoading, error, data, state, isFetching } = useQuery(['getListData', id],
    () => fetchList(id).then(res => res.data));

  if (error) {
    return 'An error has occurred: ' + error.message
  }

  if (isLoading) {
    return 'data is loading.'
  }

  return <div>
    {data.map(l => <div key={l.id}>
      {l.name}
    </div>)}
    <button onClick={() => setId(id + 1)}>按钮</button>
  </div>;

2.2 useMutation

useMutation的主要作用是清除缓存,更新和删除数据

    const queryClient = useQueryClient();

    // Mutations
    const mutation = useMutation(removeList, {
     onSuccess: () => {
       // Invalidate and refetch
       queryClient.invalidateQueries('getListData')
     },
   });
   
 <button onClick={()=> mutation.mutate({id:'0',text:'文字'})}>按钮</button>

2.3 使用devtools

import { ReactQueryDevtools } from 'react-query/devtools';
function App() {
  const queryClient = new QueryClient();
  return <div className='app'>
    <QueryClientProvider client={queryClient}>
      <List />
      <List1/>
      <ReactQueryDevtools initialIsOpen={false} position='top-right'/>
    </QueryClientProvider>
  </div>
};

在这里插入图片描述

2.4 乐观更新

乐观更新就是在一些请求或者数据处理没有结束的时候,提前给用户显示理想的结果,如果失败就回滚更新

const useAddConfig = (queryKey) => {
  // 获取当前QueryClient的实例
  const queryClient = useQueryClient()
  
  return {
    // 当mutate被调用时触发
    async onMutate(target) {
      // 获取当前数据快照,用于错误时回滚更新
      const previousItems = queryClient.getQueryData(queryKey)
      // 乐观更新为新值
      queryClient.setQueryData(queryKey, (old) => {
        return (target, old) => (old ? [...old, target] : [])
      })

      // 这个返回值会作为最后一个参数传递给onError和onSettled
      return { previousItems }
    },
    // 成功回调 清除缓存
    onSuccess: () => queryClient.invalidateQueries(queryKey),
    // 失败回调
    onError(error, newItem, context) {
      // 当前queryKey的数据回滚
      queryClient.setQueryData(
        queryKey,
        context.previousItems
      )
    },
    // 无论错误或者成功都会触发,此例子没有使用
    onSettled() {}
  }
}

传送门:react-query官网

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值