TanStack Query 被高估了?这 5 个场景它真不如 alova

⚠️ 【待 review】

TanStack Query 被高估了?这 5 个场景它真不如 alova

TL;DR --- 如果你只用 TanStack Query 做基础的「获取数据 + 缓存」,那它确实够用。但当你遇到分页、表单、上传、跨组件通信这些「真实世界的复杂请求场景」时,alova 的策略钩子能让你少写 70% 的样板代码。


先说两句

我用了两年的 TanStack Query,一度觉得它就是前端请求库的终局形态。稳定、社区大、文档好------看起来没什么毛病。

直到我开始做一个中后台管理系统,表单、分页、上传、轮询、跨组件通信......全来了。我才意识到一件事:

TanStack Query 给你的只是一个「增强版 fetcher」,它把所有复杂度都留给了你。

而 alova 给了你一套完整的请求策略

不是某个特性碾压,而是在完整的产品级场景中,alova 的体验断层式领先。下面我用 5 个真实场景来证明。


场景 1:表单提交

Before --- TanStack Query + React Hook Form

tsx 复制代码
// TanStack Query 没有原生表单钩子
// 你需要手动管理提交、重置、草稿、验证
const { mutateAsync } = useMutation({
  mutationFn: (data) => axios.post('/api/form', data),
})

const { register, handleSubmit, reset } = useForm({
  // 手动管理草稿持久化
  defaultValues: loadFromDraft()
})

// 监听表单变化存草稿
useEffect(() => {
  saveDraft(watch())
}, [watch()])

After --- alova

tsx 复制代码
const {
  loading, submit, updateForm, reset,
  form, // 响应式表单数据
} = useForm(
  (formData) => alova.Post('/api/form', formData),
  {
    // 自动草稿持久化,页面刷新后恢复
    store: true,
    // 提交后自动重置
    resetAfterSubmiting: true,
  }
)

// 完了。就这么简单。

alova 的 useForm 内置了草稿持久化、多步骤状态共享、提交后自动重置。不需要 useEffect、不需要外部表单库、不需要手动存 localStorage。

如果你做的系统需要 10 个表单,useForm 能让你省掉至少 200 行草稿管理代码。


场景 2:分页 / 无限滚动

Before --- TanStack Query

tsx 复制代码
// 手动管理页码,手动拼接 keepPreviousData
const [page, setPage] = useState(1)
const { data, isPreviousData } = useQuery({
  queryKey: ['list', page],
  queryFn: () => fetch(`/api/list?page=${page}`),
  keepPreviousData: true,
})

这还只是最基础的。一旦你想要的下一页预加载、编辑某条数据后更新列表、删除某条后从列表中移除------你就得写额外的逻辑:

tsx 复制代码
const queryClient = useQueryClient()

const prefetchNext = () => {
  queryClient.prefetchQuery(['list', page + 1], ...)
}

useEffect(() => {
  if (data?.length < pageSize) return
  prefetchNext()
}, [page, data])

After --- alova

tsx 复制代码
const {
  data, loading, page, pageSize,
  handlePrevPage, handleNextPage,
  reload, // 刷新当前页
} = usePagination(
  (page, pageSize) => alova.Get('/api/list', {
    params: { page, pageSize }
  }),
  {
    preloadNextPage: true,      // 自动预加载下一页
    total: res => res.total,
    pageSize: 20,
  }
)

// 编辑后自动更新列表项
const { send: editItem } = useRequest(
  (newData) => alova.Put('/api/item', newData),
  {
    behavior: 'silent',
    onSuccess: () => {
      // 自动替换列表中的对应项,无需手动查找替换
    }
  }
)

// 删除后自动从列表中移除
const { send: deleteItem } = useRequest(
  (id) => alova.Delete(`/api/item/${id}`),
  {
    behavior: 'silent',
    onSuccess: () => {
      // 自动从列表中移除
    }
  }
)

三个字:开箱即用。


场景 3:自动轮询 + 焦点刷新

Before --- TanStack Query

tsx 复制代码
const { data } = useQuery({
  queryKey: ['notification'],
  queryFn: () => fetch('/api/notification'),
  refetchInterval: 5000,
  refetchOnWindowFocus: true,
})

看起来还行,对吧?但一旦你要控制什么时候轮询、什么时候停止、节流控制------你就开始写「控制轮询的代码」了:

tsx 复制代码
const [enabled, setEnabled] = useState(false)

const { data } = useQuery({
  queryKey: ['notification'],
  queryFn: () => fetch('/api/notification'),
  refetchInterval: enabled ? 5000 : false,
  refetchOnWindowFocus: enabled,
})

After --- alova

tsx 复制代码
const { loading, data, stop, resume } = useAutoRequest(
  () => alova.Get('/api/notification'),
  {
    enablePoll: true,
    pollInterval: 5000,
    // 内置智能节流:浏览器不可见时不请求
    enableThrottle: true,
    // 焦点回归时自动刷新
    enableVisibility: true,
  }
)

// 按需控制
stop()   // 暂停
resume() // 恢复

alova 的 useAutoRequest 把轮询、焦点刷新、节流、可见性控制整合到一个钩子里。你不需要想「我要不要开启轮询」,而只需要想「什么时候轮询、什么时候停」。


场景 4:跨组件请求通信

在真实项目中,往往是 A 组件新增了数据,B 组件需要刷新。或者 C 组件更新了某条记录,D 组件需要知道。

Before --- TanStack Query

tsx 复制代码
// A 组件
const mutation = useMutation({
  mutationFn: (data) => axios.post('/api/item', data),
  onSuccess: () => {
    // 需要手动 invalidate
    queryClient.invalidateQueries({ queryKey: ['list'] })
  },
})

// B 组件也用了 'list' 这个 key
// 但如果你有个组件依赖于更新后的单条数据......

问题是:随着组件数量增加,invalidateQueries 调用散落在各处,你很难追踪「谁 invalidate 了谁」。

After --- alova

tsx 复制代码
// 定义方法实例时用 name 标记
const getTodoList = (keyword) =>
  alova.Get('/api/todo/list', {
    name: 'todoList',
    params: { keyword }
  })

const updateTodo = (id, data) =>
  alova.Put(`/api/todo/${id}`, data, {
    // 命中 'todoList' 的缓存自动失效
    hitSource: 'todoList',
  })

// 或者用 actionDelegationMiddleware 实现跨组件调用
// A 组件
const { send } = useRequest(updateTodo, {
  middleware: actionDelegationMiddleware('updateTodo')
})

// B 组件(非父子关系)
accessAction('updateTodo', ({ send }) => {
  send()
})

不需要理解 queryClient、不需要追踪 queryKey 图谱。 声明式的 hitSource 和函数式的 actionDelegationMiddleware 让跨组件通信变得一目了然。


场景 5:文件上传

Before --- TanStack Query

TanStack Query 没有内置的文件上传支持。你需要:

tsx 复制代码
// 自己封装上传逻辑
const uploadMutation = useMutation({
  mutationFn: async (file: File) => {
    const formData = new FormData()
    formData.append('file', file)

    const { data } = await axios.post('/api/upload', formData, {
      onUploadProgress: (e) => {
        // 手动管理进度状态
        setProgress(Math.round((e.loaded * 100) / e.total))
      }
    })
    return data
  },
})

上传多个文件?并发控制?暂停/恢复?全部自己写。

After --- alova

tsx 复制代码
const {
  upload, // 触发上传
  loading,
  progress, // 实时进度
} = useUploader(({ file, name }) =>
  alova.Post('/api/upload', {
    file, name
  })
)

// 多文件并发上传
const { upload } = useUploader(
  ({ file }) => alova.Post('/api/upload', { file }),
  {
    limit: 3, // 最多 3 个文件并发
  }
)

// 暂停/恢复上传
controller.pause()
controller.resume()

6 个属性就能实现一个完整的文件上传组件。 TanStack Query 根本不做这件事------它假装上传不存在。


总结一下

场景 TanStack Query alova
基础 GET 请求 ✅ 够用 ✅ 够用
表单提价草稿/重置 ❌ 自己写 ✅ useForm
分页 + 预加载 + 列表操作 ❌ 自己写 ✅ usePagination
智能轮询 + 节流 ❌ 自己写 ✅ useAutoRequest
跨组件通信 ❌ invalidateQueries ✅ hitSource / actionDelegation
文件上传 + 并发控制 ❌ 自己写 ✅ useUploader

我不是说 TanStack Query 不好。它是个优秀的库。但是在真实产品开发中,当你的请求场景从「获取数据」扩展到「管理数据」时,alova 的策略化方案带来的效率提升是断崖式的。

如果你还只用它做简单的 GET 请求 + 缓存,试试它的策略钩子------你会发现,原来「请求」这件事可以这么简单。


📦 alova v3 现已正式发布 | GitHub | 官网

相关推荐
颂love2 小时前
Vue3基础入门
前端·学习·vue3
风吹夏回2 小时前
Vue 3 路由使用完全指南
前端·vue.js
创业之路&下一个五年2 小时前
JS编程范式 \& 面向对象范式
开发语言·前端·javascript
ct9782 小时前
Axios 请求取消
前端·javascript·vue.js
IT_陈寒2 小时前
Redis客户端连接池不关闭的后果,程序直接崩给我看
前端·人工智能·后端
怕浪猫2 小时前
Electron 开发实战(九):调试技巧与开发者工具|测试、性能分析、日志追踪全解
前端·javascript·electron
喜欢踢足球的老罗2 小时前
产品方案:从已有 CRM AI 系统切入 WhatsApp Chrome 插件赛道
前端·人工智能·chrome
无心使然2 小时前
OpenLayers 10.9.0 渲染架构分析
前端·gis·数据可视化
智能制造产品经理代码提升2 小时前
ES6+ 标准使用手册
前端·javascript·es6