You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

本地环境useQuery仅首次加载数据不重复请求,生产环境正常

React中useQuery仅首次加载获取数据的问题解决

问题原因分析

  1. useQuery默认缓存机制:useQuery核心特性是缓存查询结果,只要查询键["todaysAbsent", branchId]不变,后续组件渲染会直接复用缓存数据,不会重新发起请求。
  2. 冗余的useState同步:你通过onSuccess将useQuery的data同步到本地useState,不仅完全没必要,还会导致数据更新不及时——当useQuery重新获取数据时,本地state不会自动同步。
  3. 错误的数组遍历用法:原代码用filter遍历数据,但filter的作用是过滤元素(需返回布尔值),而非遍历执行副作用,这属于API误用。

解决方案

1. 移除冗余useState,用useMemo处理数据转换

useQuery本身会管理数据状态,直接基于返回的allAttendance用useMemo处理数据,避免重复计算:

const {
  data: allAttendance,
  isLoading: attendanceIsLoading,
  isError: attendanceIsError,
} = useQuery(
  ["todaysAbsent", branchId],
  async () => myAxios(`/all_attendance/${moment().format("MM")}/${moment().format("YYYY")}/?branch_id=${branchId ?? ""}`)
);

// 用useMemo处理数据转换,仅在allAttendance变化时重新计算
const todayAttendance = React.useMemo(() => {
  if (!allAttendance?.data) return [];
  return Object.values(allAttendance.data).map(({ attendance, name, position, information_user }, i) => ({
    attendance: attendance[moment().format("YYYY-MM-DD")],
    id: i,
    status: attendance[moment().format("YYYY-MM-DD")]?.status, // 加可选链避免报错
    name,
    position,
    information_user
  }));
}, [allAttendance]);

2. 配置useQuery的重新获取策略

根据业务需求选择以下方式触发重复获取:

  • 窗口聚焦时自动刷新:适合用户切回页面需要更新数据的场景
    const { ... } = useQuery(
      ["todaysAbsent", branchId],
      async () => {/* 请求逻辑 */},
      { refetchOnWindowFocus: true } // 默认开启,若之前设为false可重新打开
    );
    
  • 设置数据过期时间:指定数据多久后变为"过期",自动重新请求
    const { ... } = useQuery(
      ["todaysAbsent", branchId],
      async () => {/* 请求逻辑 */},
      { staleTime: 60000 } // 1分钟后数据过期,下次渲染自动请求
    );
    
  • 手动触发刷新:通过refetch方法在特定时机(如按钮点击)主动发起请求
    const {
      data: allAttendance,
      isLoading: attendanceIsLoading,
      isError: attendanceIsError,
      refetch // 获取手动刷新方法
    } = useQuery(
      ["todaysAbsent", branchId],
      async () => {/* 请求逻辑 */}
    );
    
    // 示例:点击按钮刷新
    const handleRefresh = () => refetch();
    

3. 确保查询键能正确触发更新

查询键["todaysAbsent", branchId]中,branchId必须是基本类型(字符串/数字)。如果branchId是引用类型(如对象),要提取其中的唯一标识作为查询键的一部分,否则useQuery会认为查询键未变化,不会重新请求。

内容的提问来源于stack exchange,提问作者Naser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 23:15:54