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

如何使用useState配合React Query(useQuery)实现动态接口参数更新获取数据

问题根因
  • useQuery的查询键是触发重新请求的核心依据,你当前使用固定字符串'productDetail'作为查询键,即使gender、age等参数更新,查询键未变化,react-query会直接复用之前的缓存结果,不会发起新请求。
  • 原有代码存在两处语法错误:
    1. 请求地址拼接时误用未定义变量female,应该用state存储的gender变量
    2. onChange事件中取字段名时写死e.target.age,应该读取输入框的name属性匹配对应字段
  • fetch配置中withCredentials是axios的参数,原生fetch对应配置为credentials: 'include',也会导致请求携带凭证异常。
修复实现

你只需要将所有影响请求结果的参数(id、gender、age)都放到查询键数组中,react-query会自动监听这些参数的变化,参数更新时自动触发重新请求,同时修正语法错误即可,完整代码如下:

import { useState } from 'react';
import { useQuery } from 'react-query';

// 假设id、token是你页面已经获取到的变量
const ProductDetailPage = ({ id, token }) => {
  // 存储用户输入的参数
  const [inputs, setInputs] = useState({
    age: '30',
    gender: 'female',
  });
  const { age, gender } = inputs;

  // 修正onChange逻辑,通过输入框name属性匹配对应字段
  const onChange = (e) => {
    setInputs({ 
      ...inputs, 
      [e.target.name]: e.target.value 
    });
  };

  // 请求函数
  const fetchDetail = async () => {
    const res = await fetch(`https://api.minsu.com/product/${id}?gender=${gender}&age=${age}`, {
      headers: {
        Authorization: `Bearer ${token}`,
      },
      credentials: 'include'
    });
    if (!res.ok) throw new Error('请求失败');
    return res.json();
  };

  // 重点:把所有请求依赖参数放到查询键数组中
  const { data: ProductDetail, status, error, isFetching } = useQuery(
    ['productDetail', id, gender, age], 
    fetchDetail, 
    {
      notifyOnChangeProps: ['data'], 
      staleTime: 100000000,
    }
  );

  // 状态兜底处理
  if (status === 'loading') return <div>加载中...</div>;
  if (status === 'error') return <div>请求错误:{error.message}</div>;

  return (
    <div>
      <div>
        <input 
          type="number" 
          name="age" 
          value={age}
          onChange={onChange} 
          placeholder="请输入年龄"
        />
        <select 
          name="gender" 
          value={gender}
          onChange={onChange}
        >
          <option value="male">男</option>
          <option value="female">女</option>
        </select>
      </div>
      
      {isFetching && <div>数据更新中...</div>}
      
      {/* 渲染详情数据 */}
      <div className="detail-content">
        <h1>{ProductDetail.title}</h1>
        <p>{ProductDetail.desc}</p>
        {/* 其他详情字段自行补充 */}
      </div>
    </div>
  );
};

export default ProductDetailPage;
可选优化

如果不需要用户每输入一个字符就立刻发请求,可以添加防抖逻辑,等用户停止输入300ms后再发起请求,避免频繁调用接口:

import { useState, useEffect } from 'react';
// ...其他引入保持不变

const ProductDetailPage = ({ id, token }) => {
  const [inputs, setInputs] = useState({ age: '30', gender: 'female' });
  // 新增防抖后的参数state
  const [debouncedInputs, setDebouncedInputs] = useState(inputs);

  const onChange = (e) => {
    setInputs({ ...inputs, [e.target.name]: e.target.value });
  };

  // 防抖逻辑
  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedInputs(inputs);
    }, 300);
    return () => clearTimeout(timer);
  }, [inputs]);

  const fetchDetail = async () => {
    // 用防抖后的参数拼接地址
    const { age, gender } = debouncedInputs;
    const res = await fetch(`https://api.minsu.com/product/${id}?gender=${gender}&age=${age}`, {
      // 其他配置保持不变
    });
    // ...其他请求逻辑保持不变
  };

  // 查询键替换为防抖后的参数
  const { data: ProductDetail, status, error, isFetching } = useQuery(
    ['productDetail', id, debouncedInputs.gender, debouncedInputs.age], 
    fetchDetail, 
    {
      staleTime: 100000000,
    }
  );

  // ...其他渲染逻辑保持不变
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 21:45:08