0%

userequest-tanstackquery-swr

ahooks.useRequest / @tanstack/react-query / swr 简单对比

叠甲: 一些个人经验, 并不是大而全的比较.

版本:

1
2
3
4
5
{
"ahooks": "^3.8.5",
"@tanstack/react-query": "^5.76.2",
"swr": "^2.3.3"
}

ahooks.useRequest

  • 简单: 返回 {loading, error, data, refresh} 够使用
  • loadingDelay: 防止 request 完成太快, 导致 loading 状态切换闪烁. 其他两个没找到类似的 options
  • 全: pollInterval / refreshDeps / refreshOnWindowFocus 等功能都实现了

缺少 stale-while-revalidate 时的 indicator, 比如

  • tanstack/react-queryisFetching or fetchStaus === 'fetching'
  • swr 中的 isValidating

swr

简洁:

  • const {isLoading, error, data, isValidating, mutate} = useSwr(key, fetcher) 只有这几个
  • mutate 承载更多功能:
    • mutate() 无参数, 承担 refetch / refresh 功能
    • mutate(undefined) 移除 data, 并 refresh, 相当于 tanstack/react-queryqueryClient.removeQuery
    • mutate 本来的意图, 修改数据
  • stale 默认情况下, 没有一个 staleTime 配置, 数据一经缓存, 会一直 fresh

当你调用 mutate(key)(或者只是使用绑定数据更改 API mutate())时没有传入任何数据,它会触发资源的重新验证(将数据标记为已过期并触发重新请求)

也许会纳闷, 实现如何区分 mutate() & mutate(undefined), 使用 args.length:

1
2
3
4
5
// If there is no new data provided, revalidate the key with current state.
if (args.length < 3) {
// Revalidate and broadcast state.
return startRevalidate()
}

mutate 表达多个意思, 个人觉得不是很好.

@tanstack/react-query

大而全, 但繁琐

槽点: 需要 QueryClientProvider

简单使用也需要 react context, 明明可以使用一个 defaultQueryClient, 并导出 getDefaultQueryClient 即可
参考 jotai: useAtom 也需要 context Store, 但支持 provider-less mode, getDefaultStore

1
2
3
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
const queryClient = new QueryClient()
const el = <QueryClientProvider client={queryClient}>more</QueryClientProvider>

用法

  • normal usage
    1
    const { isPending, data, error, isFetching, refetch } = useQuery({ queryKey, queryFn, ...moreOptions })
  • Poll效果: refetchInterval
  • invalidate & remove
    • 通过 queryClient.invalidateQueries or refetch() 重新获取数据
    • 通过 queryClient.removeQueries + refetch() 实现 initial hard-loading
  • aggressive but sane defaults
    • 默认 staleTime = 0, by default consider cached data as stale.
    • Stale queries are refetched automatically in the background when
      • New instances of the query mount refetchOnMount
      • The window is refocused refetchOnWindowFocus
      • The network is reconnected refetchOnReconnect
      • The query is optionally configured with a refetch interval refetchInterval

Snippets

top-loading-bar

1
2
3
4
5
6
7
8
9
10
11
import { useQuery, useQueryClient } from '@tanstack/react-query'
import { BarLoader } from 'react-spinners'

const { isPending, isFetching } = useQuery({ queryKey, queryFn })

// 独立于页面的 Loading, 绑定到 `isFetching`
const topLoadingBar = isFetching && (
<div className='fixed top-0 inset-x-0'>
<BarLoader width={'100%'} color='#f69' />
</div>
)

总结

lightweight: ahooks.useRequest > swr > @tanstack/react-query

如果只是需要 loading / error / data, 避免自己手动 useEffect / setState, 使用 ahooks.useRequest 即可
重一点的推荐 @tanstack/react-query