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

如何向React Query自定义Hook传递参数?

问题分析

你的自定义Hook useUserInfo 将 token 作为Hook的参数,但调用 refetch 时无法修改Hook的参数(Hook参数仅在组件渲染阶段生效),导致查询函数始终使用初始化时的token(此处初始化未传值,因此为undefined)。同时,refetch 的参数会直接传递给查询函数,而非自定义Hook本身,所以你之前的写法无法将token传递给fetchUserInfo。

解决方案

方案一:通过组件状态管理token,让React Query自动触发查询(推荐)

利用查询键的变化自动触发新查询,符合React Query的设计理念:

  1. 修改自定义Hook,将token加入查询键,确保token变化时自动执行新查询:
export const useUserInfo = (enabled, token) => {
  return useQuery(
    ["users-info", token], // token变化时,React Query判定为新查询,自动重新执行
    () => fetchUserInfo(token),
    {
      enabled: enabled, // 仅当token存在时启用查询
    },
  );
};
  1. 在组件中管理token状态,获取到token后更新状态,useQuery会自动处理后续查询:
const Auth = () => {
  const [token, setToken] = useState(null);
  const { data: userInfo, isSuccess, isError, error } = useUserInfo(!!token, token);
  const dispatch = useDispatch();
  const navigate = useNavigate();

  // 用户信息获取成功后执行后续操作
  useEffect(() => {
    if (isSuccess && userInfo) {
      dispatch({ type: "SET_USER", payload: userInfo });
      navigate("/");
      location.reload();
    }
  }, [isSuccess, userInfo, dispatch, navigate]);

  // 处理查询错误
  useEffect(() => {
    if (isError) {
      console.error(error);
    }
  }, [isError, error]);

  const handleLoginPopup = async () => {
    try {
      const newToken = "abcd121212"; // 实际为登录接口返回的token
      setToken(newToken);
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <button onClick={handleLoginPopup}>登录</button>
  );
};

方案二:通过refetch传递参数给查询函数(适合无需按token缓存的场景)

如果确实需要手动调用refetch传递token,可以修改查询函数接收refetch的参数:

  1. 调整自定义Hook,让查询函数读取refetch传入的参数:
export const useUserInfo = (enabled) => {
  return useQuery(
    ["users-info"], // 无需按token缓存时,查询键固定
    ({ refetchArg }) => {
      const { token } = refetchArg;
      if (!token) {
        throw new Error("Token is required");
      }
      return fetchUserInfo(token);
    },
    {
      enabled: enabled, // 初始不启用查询
    },
  );
};
  1. 在组件中调用refetch时直接传递token:
const Auth = () => {
  const { refetch } = useUserInfo(false);
  const dispatch = useDispatch();
  const navigate = useNavigate();

  const handleLoginPopup = async () => {
    try {
      const token = "abcd121212";
      // 调用refetch并传递token参数
      const { data: userInfo } = await refetch({ token });
      
      dispatch({ type: "SET_USER", payload: userInfo });
      navigate("/");
      location.reload();
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <button onClick={handleLoginPopup}>登录</button>
  );
};

注意:方案二的查询键固定,不同token的结果会覆盖同一缓存。若需要为每个token单独缓存数据,优先使用方案一。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 22:17:35