如何仅在queryKey变化时通过react-query点击按钮获取数据?
解决方案
要实现「仅在Play按钮点击且输入参数变化时发起请求」的需求,核心思路是手动跟踪上一次请求的参数,在点击时对比当前参数与历史参数,仅当参数变化(或首次点击)时触发请求。以下是具体实现方案:
步骤1:在组件中跟踪历史请求参数
在使用useFetchVoiceSample的组件里,新增状态保存上一次发起请求的参数,用来和当前输入值做对比。
步骤2:控制Play按钮的请求触发逻辑
点击按钮时,先判断当前参数是否和历史参数一致:
- 首次点击(无历史参数):直接发起请求并记录当前参数
- 参数有变化:发起请求并更新历史参数
- 参数无变化:不执行任何请求操作
完整代码示例
组件实现
import { useState } from 'react'; import { useFetchVoiceSample } from './your-hook-file-path'; // 假设你的参数类型定义 type GetVoiceSamplePayload = { id: string; language: string; accent: string; expressiveness: number; }; const VoiceSamplePlayer = () => { // 表单输入状态(示例,实际根据你的表单逻辑调整) const [id] = useState('voice-001'); const [language, setLanguage] = useState('zh-CN'); const [accent, setAccent] = useState('mandarin'); const [expressiveness, setExpressiveness] = useState(50); // 保存上一次发起请求的参数 const [lastRequestedParams, setLastRequestedParams] = useState<GetVoiceSamplePayload | null>(null); // 调用自定义Query Hook const { refetch, data, isLoading } = useFetchVoiceSample({ id, language, accent, expressiveness, }); // 处理Play按钮点击事件 const handlePlayClick = () => { const currentParams = { id, language, accent, expressiveness }; // 判断是否需要发起请求:首次点击 或 参数发生变化 const needRefetch = !lastRequestedParams || ( currentParams.id !== lastRequestedParams.id || currentParams.language !== lastRequestedParams.language || currentParams.accent !== lastRequestedParams.accent || currentParams.expressiveness !== lastRequestedParams.expressiveness ); if (needRefetch) { refetch(); setLastRequestedParams(currentParams); } }; return ( <div className="voice-sample-form"> {/* 滑块1:Expressiveness */} <div> <label>表现力:{expressiveness}</label> <input type="range" min="0" max="100" value={expressiveness} onChange={(e) => setExpressiveness(Number(e.target.value))} /> </div> {/* 下拉选择:Language */} <div> <label>语言:</label> <select value={language} onChange={(e) => setLanguage(e.target.value)}> <option value="zh-CN">中文</option> <option value="en-US">英文</option> </select> </div> {/* 下拉选择:Accent */} <div> <label>口音:</label> <select value={accent} onChange={(e) => setAccent(e.target.value)}> <option value="mandarin">普通话</option> <option value="cantonese">粤语</option> </select> </div> {/* Play按钮 */} <button onClick={handlePlayClick} disabled={isLoading}> {isLoading ? '加载中...' : 'Play'} </button> {/* 渲染返回的音频数据 */} {data && <audio src={data.audioUrl} controls autoPlay />} </div> ); }; export default VoiceSamplePlayer;
原Hook无需修改
你提供的useFetchVoiceSample Hook保持不变即可,它负责定义查询的queryKey和请求逻辑,由组件控制何时触发refetch。
关键说明
- 采用逐个字段对比的方式判断参数变化,比
JSON.stringify更高效,也避免了对象属性顺序等无关因素导致的误判。 lastRequestedParams仅记录实际发起请求的参数,确保后续对比的准确性。- 结合
isLoading状态禁用按钮,避免重复点击导致的并发请求。
内容的提问来源于stack exchange,提问作者qweezz
相关产品推荐
相关产品推荐

