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
相关产品推荐
相关产品推荐

