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

点击提交按钮时React Query重复调用API两次的问题求助

问题描述

点击提交按钮后,API被调用两次:一次参数为{},一次携带有效参数。期望仅调用一次有效请求。

组件代码

const [filter, setFilter] = useState(null);
const [typeReport, setTypeReport] = useState("");
const { data: reportBusiness, isFetching } = useGetReportBusiness(
  {
    ...filter,
  },
  typeReport
);
const {
  page,
  pageSize,
  handleChangePage,
  handleChangePageSize,
  clientData,
  clientTotal,
} = usePagination(reportBusiness);

const handleSubmit = (values) => {
  const from = moment(values.dateRange[0]).toISOString();
  const to = moment(values.dateRange[1]).toISOString();
  setTypeReport(values.typeReport);

  setFilter({
    from,
    to,
  });
  handleChangePage(1);
};

查询函数代码

export const useGetReportBusiness = (params, typeReport) => {
  return useQuery({
    queryKey: [QUERY_KEYS.REPORT_BUSINESS, params, typeReport],
    queryFn: async () => {
      console.log("11");
      let res;
      if (typeReport === BUSINESS_CSKH_VALUE) {
        res = await ReportBusinessApi.getReportBusinessCSKH(params);
      } else {
        res = await ReportBusinessApi.getReportBusinessBCP(params);
      }

      return res.data?.data;
    },
  });
};

版本信息

"react": "^18.2.0",
"@tanstack/react-query": "^5.0.0-alpha.71",
原因分析
  • 多次状态更新触发重渲染:handleSubmit中先后调用setTypeReport和setFilter,两次异步状态更新会导致组件两次重渲染,每次重渲染都会触发useGetReportBusiness执行。第一次重渲染时filter未完成更新,参数为{};第二次重渲染时两个状态都已更新,携带有效参数。
  • React 18严格模式影响:开发环境下,React 18的严格模式会重复执行副作用逻辑(包括useQuery内部的请求触发),进一步加剧重复调用问题。
解决方案

方案1:合并状态,减少重渲染次数

将filter和typeReport合并为一个状态对象,一次setState完成所有更新,避免多次重渲染:

const [reportParams, setReportParams] = useState({
  filter: null,
  type: ""
});

const { data: reportBusiness, isFetching } = useGetReportBusiness(
  reportParams.filter || {},
  reportParams.type
);

const handleSubmit = (values) => {
  const from = moment(values.dateRange[0]).toISOString();
  const to = moment(values.dateRange[1]).toISOString();
  setReportParams({
    filter: { from, to },
    type: values.typeReport
  });
  handleChangePage(1);
};

方案2:给useQuery添加enabled条件,仅在参数有效时发起请求

在查询函数中添加enabled选项,确保只有当参数完整有效时才触发API请求:

export const useGetReportBusiness = (params, typeReport) => {
  // 判断参数是否有效:params存在from/to,且typeReport不为空
  const isEnabled = !!params?.from && !!params?.to && !!typeReport;
  
  return useQuery({
    queryKey: [QUERY_KEYS.REPORT_BUSINESS, params, typeReport],
    queryFn: async () => {
      console.log("11");
      let res;
      if (typeReport === BUSINESS_CSKH_VALUE) {
        res = await ReportBusinessApi.getReportBusinessCSKH(params);
      } else {
        res = await ReportBusinessApi.getReportBusinessBCP(params);
      }

      return res.data?.data;
    },
    enabled: isEnabled
  });
};

方案3:临时关闭React 18严格模式(仅开发环境验证)

如果是严格模式导致的重复调用,可暂时移除index.js中的<React.StrictMode>标签,但不建议长期使用——严格模式有助于提前发现代码潜在问题。

内容的提问来源于stack exchange,提问作者Lăng Rover

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 19:55:40