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

React Query中使用axios.request(options)时变量参数失效问题求助

问题原因分析

你的问题核心在于状态更新的异步性和查询函数未使用最新参数:

  1. 调用setTvSearchQuery(data.tvSearch)后,React状态更新是异步的,立刻执行refetch()时,tvSearchQuery还未完成更新,导致请求参数仍是旧值。
  2. options对象随组件渲染创建,但fetchTvData直接引用外部的options,当搜索关键词更新后,查询函数可能无法捕获最新的请求配置。
修复方案

方案1:让查询函数接收明确参数

将搜索关键词作为参数传入查询函数,确保每次请求都使用最新值:

import { useQuery } from "react-query";
import axios from "axios";
import { Stack, TextField, Button } from "@mui/material";
import { useForm } from "react-hook-form";
import { useState } from "react";

interface FormValues {
  tvSearch: string;
}
interface Tv {
  id: number;
}
interface ShowData {
  data: Tv[];
}

function ShowBox() {
  const [tvSearchQuery, setTvSearchQuery] = useState("");
  const form = useForm<FormValues>({
    defaultValues: {
      tvSearch: "",
    },
  });
  const { register, handleSubmit, formState } = form;
  const { errors } = formState;

  // 让fetchTvData接收搜索关键词参数,内部创建请求配置
  function fetchTvData(searchQuery: string): Promise<ShowData> {
    return axios.request({
      method: "GET",
      url: "https://api.themoviedb.org/3/search/tv",
      params: {
        query: searchQuery,
        include_adult: "false",
        language: "en-US",
        page: "1",
      },
      headers: {
        accept: "application/json",
        Authorization: "Bearer key1234",
      },
    });
  }

  function onSubmit(data: FormValues) {
    setTvSearchQuery(data.tvSearch);
    // 直接传入表单的最新值触发查询
    refetch(data.tvSearch);
  }

  function onSuccess(data: ShowData) {
    console.log("success", data);
  }
  function onError(error: Error) {
    console.log("ERROR", error);
  }

  const { data, refetch } = useQuery({
    queryKey: ["tvSearchQuery", tvSearchQuery],
    // 使用queryKey中的参数作为查询函数输入
    queryFn: () => fetchTvData(tvSearchQuery),
    refetchOnWindowFocus: false,
    enabled: false,
    onSuccess,
    onError,
  });

  console.log(data?.data);
  return (
    <form onSubmit={handleSubmit(onSubmit)} noValidate>
      <Stack spacing={2}>
        <TextField
          label="输入剧集或电影名称"
          type="text"
          {...register("tvSearch")}
          error={!!errors.tvSearch}
          helperText={errors.tvSearch?.message}
        />
        <Button type="submit" variant="contained">
          搜索
        </Button>
      </Stack>
    </form>
  );
}

方案2:通过refetch传递参数

如果不想修改查询函数结构,可借助refetch的参数传递能力:

// ... 其他代码不变
function onSubmit(data: FormValues) {
  // 直接使用表单提交的最新值,不依赖异步状态更新
  refetch(data.tvSearch);
}

const { data, refetch } = useQuery({
  queryKey: ["tvSearchQuery", tvSearchQuery],
  // 从queryKey或refetch参数中获取最新搜索关键词
  queryFn: ({ queryKey }) => {
    const [_, searchQuery] = queryKey;
    return axios.request({
      ...options,
      params: { ...options.params, query: searchQuery },
    });
  },
  refetchOnWindowFocus: false,
  enabled: false,
  onSuccess,
  onError,
});
关键要点总结
  • 避免依赖异步状态更新:表单提交时直接使用表单数据,不要等待setState完成。
  • 保持查询键与请求参数一致:React Query会根据queryKey的变化触发重新查询,确保查询函数使用的参数和queryKey同步。
  • 不要让查询函数依赖外部可变对象:尽量在查询函数内部创建请求配置,或传递明确参数,避免引用外部可能过时的对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 22:16:02