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

使用TanStack Query时UI未随ID变更重新渲染的问题排查

问题:TanStack Query ID变更时UI不更新,仅切换标签页后生效

我用TanStack Query封装了自定义Hook获取API数据,ID参数传递正常,但ID变更时UI不会自动更新,只有切换标签页返回后才会更新。但用普通Axios请求的代码可以正常更新UI,求解决。

自定义Hook代码:

import { useQuery } from "@tanstack/react-query";
import { ApiInstance } from "../axios/axios";
import { Endpoints } from "../endpoints/endpoints";

export const useGetApiDetails = (id) => {
  const { data, isLoading } = useQuery(["getApiDetails"], {
    queryFn: async () => {
      const { data } = await ApiInstance.get(Endpoints.getApiDetails(id));
      return data;
    },
  });
  return { data, isLoading };
};

Home组件使用代码:

const Home = () => {
  const { pathname } = useLocation();
  const id = pathname.replace("/", "");
  const { data, isLoading } = useGetApiDetails(id);
  const [apiDetails, setApiDetails] = useState();
  const [requestParamList, setRequestParamList] = useState();

  useEffect(() => {
    setApiDetails(data?.data?.apiDetails);
    setRequestParamList(data?.data?.requestParamList);
  }, [data]);

  return (
    <div className="w-full h-full flex">
      {/* {isLoading ? (
        <h1>Loading...</h1>
      ) : ( */}
      <>
        <LeftSide apiDetails={apiDetails} requiredParams={requestParamList} />
        <RightSide apiDetails={apiDetails} requiredParams={requestParamList} />
      </>
      {/* )} */}
    </div>
  );
};

export default Home;

正常工作的普通Axios代码:

const { pathname } = useLocation();
const id = pathname.replace("/", "");
const [apiDetails, setApiDetails] = useState();
const [requestParamList, setRequestParamList] = useState();

const fetchData = async (id) => {
    const response = await ApiInstance.get(Endpoints.getApiDetails(id))
    console.log(response.data, "res");
    setApiDetails(response.data.data.apiDetails)
    setRequestParamList(response.data.data.requestParamList)
}

useEffect(() => {
  fetchData(id)
}, [id]);

解决方案

1. 修复自定义Hook的查询键

TanStack Query 通过**查询键(Query Key)**识别不同请求、管理缓存并决定是否重新发起请求。你的代码里查询键是固定的["getApiDetails"],未包含id参数,导致id变化时,TanStack Query认为是同一个请求,不会重新调用queryFn。

修改自定义Hook,把id加入查询键:

export const useGetApiDetails = (id) => {
  const { data, isLoading } = useQuery(
    ["getApiDetails", id], // 将id加入查询键,让键随id动态变化
    {
      queryFn: async () => {
        const { data } = await ApiInstance.get(Endpoints.getApiDetails(id));
        return data;
      },
    }
  );
  return { data, isLoading };
};

2. 移除冗余的状态和副作用

Home组件里用useState和useEffect同步TanStack Query返回的data完全没必要,直接使用data即可减少冗余代码,同时避免状态不同步问题:

const Home = () => {
  const { pathname } = useLocation();
  const id = pathname.replace("/", "");
  const { data, isLoading } = useGetApiDetails(id);

  // 直接从data解构需要的字段
  const apiDetails = data?.data?.apiDetails;
  const requestParamList = data?.data?.requestParamList;

  return (
    <div className="w-full h-full flex">
      {isLoading ? (
        <h1>Loading...</h1>
      ) : (
        <>
          <LeftSide apiDetails={apiDetails} requiredParams={requestParamList} />
          <RightSide apiDetails={apiDetails} requiredParams={requestParamList} />
        </>
      )}
    </div>
  );
};

export default Home;

原因说明

  • 普通Axios代码中,useEffect监听id变化,每次id改变都会重新调用fetchData,因此UI能正常更新。
  • TanStack Query默认缓存请求结果,只有当查询键变化时才会重新发起请求。之前的查询键不包含id,所以id变化不会触发新请求;切换标签页时,TanStack Query会触发后台重新获取数据,这才让UI更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 02:13:26