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

React中表格链接多次点击无法触发API调用问题求助

问题分析与修复方案

问题核心在于RTK Query的缓存机制以及状态更新逻辑:

  • 首次点击时,headerSkValue从null变为目标值,skip条件切换为false,触发API调用。
  • 第二次点击时,若为同一行(值相同),RTK Query会直接返回缓存结果,不会发起新请求;若为不同行,若headerSkValue直接从旧值改为新值,skip条件始终为false,且缓存未过期时仍会复用缓存数据,不会触发新请求。

修复方案1:使用refetch强制触发请求

RTK Query的useQuery钩子提供了refetch方法,可直接调用它并传递最新变量,绕开缓存限制:

import React, { useState, useEffect } from 'react';
import { useGetInvoicePdfQuery } from 'your-api-library';

function App() {
  const [pdfBlob, setPdfBlob] = useState<Blob | null>(null);
  const [pdfUrl, setPdfUrl] = useState<string | null>(null);
  const [headerSkValue, setHeaderSkValue] = useState<number | null>(null);

  // 解构出refetch方法
  const { data, loading, error, refetch } = useGetInvoicePdfQuery({
    query: invoicePdfQuery,
    variables: {
      hdrSk: headerSkValue,
    },
    skip: headerSkValue === null,
  });

  useEffect(() => {
    if (data) {
      // PDF转换逻辑保持不变
      const decodedPdfData = window.atob(data);
      const byteArray = new Uint8Array(decodedPdfData.length);
      for (let i = 0; i < decodedPdfData.length; i++) {
        byteArray[i] = decodedPdfData.charCodeAt(i);
      }
      const pdfBlob = new Blob([byteArray.buffer], { type: 'application/pdf' });
      setPdfBlob(pdfBlob);

      const pdfUrl = URL.createObjectURL(pdfBlob);
      setPdfUrl(pdfUrl);

      if (headerSkValue !== null) {
        window.open(pdfUrl, '_blank');
      }
    }
  }, [data, headerSkValue]);

  // 修改点击事件:设置值后强制触发请求
  const handleButtonClick = (targetHdrSk) => {
    setHeaderSkValue(targetHdrSk);
    refetch({ hdrSk: targetHdrSk });
  };

  // 清理Object URL,避免内存泄漏
  useEffect(() => {
    return () => {
      if (pdfUrl) {
        URL.revokeObjectURL(pdfUrl);
      }
    };
  }, [pdfUrl]);

  return (
    <div>
      {/* 表格行中需传递对应row的hdrSk值 */}
      <button onClick={() => handleButtonClick(yourHeaderValue)}>Open PDF in New Tab</button>
      {loading && <p>Loading...</p>}
      {error && <p>Error: {error.message}</p>}
      {pdfBlob && (
        <div>
          <button onClick={() => window.open(pdfUrl, '_blank')}>Open PDF in New Tab</button>
          <object
            data={pdfUrl}
            type="application/pdf"
            width="100%"
            height="600px"
          >
            Your browser does not support PDFs.
          </object>
        </div>
      )}
    </div>
  );
}

export default App;

修复方案2:修改缓存策略,强制每次请求

在useGetInvoicePdfQuery配置中设置staleTime和cacheTime为0,让RTK Query认为数据立即过期,每次都发起新请求:

const { data, loading, error } = useGetInvoicePdfQuery({
  query: invoicePdfQuery,
  variables: {
    hdrSk: headerSkValue,
  },
  skip: headerSkValue === null,
  staleTime: 0, // 数据立即标记为过期
  cacheTime: 0, // 缓存立即清理
});

修复方案3:先重置状态再设置新值

点击时先将headerSkValue设为null,触发skip为true,再设置目标值,强制查询重新执行:

const handleButtonClick = (targetHdrSk) => {
  // 先重置为null,触发skip逻辑
  setHeaderSkValue(null);
  // 确保状态更新完成后再设置新值
  setTimeout(() => {
    setHeaderSkValue(targetHdrSk);
  }, 0);
};

额外注意事项

  • 表格每行的链接需传递对应行的hdrSk值,例如:onClick={() => handleButtonClick(row.hdrSk)}。
  • 必须添加URL.revokeObjectURL的清理逻辑,避免浏览器内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 18:35:07