解决react状态管理---React Query

解决react状态管理---React Query_第1张图片

什么是React Query

  • react-query是一个适用于react hooks的请求库,它可以为任何类型的异步数据提供React状态管理功能,使React中的获取、缓存、同步和更新服务器数据变得轻而易举
  • react-query与一些传统的状态管理库如redux,mobx不同,它是负责管理服务器与客户端之间的状态,一些用户交互的中间状态,如loading状态,错误信息等都是通过hooks直接返回
  • React Query官网

初步使用

  1. yarn add react-query or npm i react-query安装react-query
  2. 使用QueryClientProvider组件连接并提供一个QueryClient到你的应用程序
import { QueryClient, QueryClientProvider } from 'react-query'

<QueryClientProvider client={new QueryClient()}>
  { ... }
</QueryClientProvider>
Devtools
  • yarn add react-query-devtools or npm i --save react-query-devtools安装Devtools
  • react-query-devtools是与react-query相匹配的开发工具
  • 可在开发中实时查看缓存,手动获取和删除查询等等
import { ReactQueryDevtools } from 'react-query-devtools'

const App = () => {
  return (
    <>    
      { ... }
      <ReactQueryDevtools initialIsOpen={true} />
    </>
  );
};

增删改查

  • react-query最常用的两个hook,查询(useQuery)、增删改(useMutation)
useQuery
  • useQuery:在React Query中,查询是对某些异步数据源的声明性依赖。查询可以与任何基于Promise的方法(GET)一起使用,从服务器获取数据
const useTodos = (param) => {
  const request = useHttp()

  /**
   * 第一个参数是QueryKey,是查询的关键,是一个独一无二的key,并在之后的增删改中需要,
   * 	如果需要动态的QueryKey,可以使用数组的方式,如['todos', params]
   * 第二个参数是用于获取数据的异步函数
   * useQuery的响应返回就是获取到的数据和一些中间状态,如isLoading,error,isIdle...
   */
  return useQuery('todos', () =>
    request('todos', { data: param })
  )
}

// 在UI组件调用
const { isLoading, error, data: todos } = useTodos()
useMutation
  • useMutation:常用于创建/更新/删除数据或执行服务器副作用
const useAddTodo = () => {
  const request = useHttp()

  /**
   * 第一个参数是执行操作的异步函数,在返回的mutate中触发
   * 第二个参数是执行成功或者失败的一些配置函数,可用于一些处理缓存的操作,例如乐观更新
   */
  return useMutation(
    (data) =>
      request(`todos`, {
        data,
        method: 'POST',
      }),
    {
      onSuccess(){}
      onError(){}
      onSettled(){}
      ...
    }
  )
}

// 操作组件调用
const TodosAddBtn = () => {
  ...
  const { mutateAsync, isLoading, error } = useAddTodo()
  return <Button onClick={() => mutateAsync(todoData)}>add</Button>
}
例:用第二个参数配置乐观更新
  • 乐观更新就是在一些请求或者数据处理没有结束的时候,提前给用户显示理想的结果,如果失败就回滚更新
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() {}
  }
}

总结

  • 本地/客户端中间状态
    • redux与react-query都可,没有较大的优缺点
  • 服务端中间状态
    • 推荐react-query,将服务器状态从全局状态中解放出来,用更少的代码实现复杂的需求,让你的状态管理更优雅

你可能感兴趣的:(react)