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

如何点击搜索按钮后使用React Query获取数据

修正React Hooks使用错误并实现城市天气查询功能

你当前的核心问题是在事件处理函数中直接调用useFetch,这违反了React Hooks的核心规则——Hooks只能在组件顶层作用域或自定义Hooks内部调用,不能在事件回调、条件判断这类嵌套逻辑里执行。以下是具体的修正方案:

第一步:修改useFetch钩子,支持城市变更触发新请求

原useFetch的queryKey未包含城市参数,React Query会默认所有请求都是同一个查询,不会主动发起新请求。我们需要把城市加入queryKey,让React Query能识别不同城市的查询需求:

import { useQuery } from "@tanstack/react-query";

const useFetch = function (city:string='kampala') {
  const { isLoading, error, data } = useQuery({
    // 将city加入queryKey,确保不同城市对应独立的查询缓存与请求
    queryKey: ["weatherData", city],
    queryFn: () =>
      fetch(
        `http://api.weatherapi.com/v1/forecast.json?key=516e576e876042b9b7665337232403&q=${city}&days=7`
      ).then((res) => res.json()),
  });

  return { isLoading, error, data };
};

export default useFetch;

第二步:修正Header组件,用状态管理触发查询

改用useState管理当前查询的城市,提交表单时更新状态,组件重新渲染后useFetch会自动接收新的城市参数并发起请求:

import React, { useState } from "react";
import useFetch from "../../../hooks/useFetch";

import "./header.css";

type Props = {};

function Header({}: Props) {
  // 用useState管理当前查询城市,默认值设为kampala,实现首次挂载自动请求
  const [currentCity, setCurrentCity] = useState<string>("kampala");
  // 顶层调用useFetch,传入当前城市参数
  const { isLoading, error, data } = useFetch(currentCity);

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    // 从表单获取输入的城市值
    const inputCity = (e.target as HTMLFormElement).city.value.trim();
    if (inputCity) {
      // 更新城市状态,触发组件重渲染与新请求
      setCurrentCity(inputCity);
      // 清空表单输入
      (e.target as HTMLFormElement).reset();
    }
    window.scrollTo({
      top: 0,
      behavior: "smooth",
    });
  };

  return (
    <div className="lovez">
      <div className="lovek">
        <h1 style={{ color: "#F5AF26" }}>Weather Forcast</h1>
        <p>{new Date().toDateString()}</p>
      </div>
      <div className="header__search">
        <form onSubmit={handleSubmit}>
          <input
            type="text"
            className="home__input"
            name="city"
            placeholder="Choose City"
          />
          <button type="submit" className="weather__button">
            Search
          </button>
        </form>
      </div>
      {/* 可根据需求添加状态展示 */}
      {isLoading && <p>加载中...</p>}
      {error && <p>请求出错,请重试</p>}
      {data && <p>当前城市:{data.location.name}</p>}
    </div>
  );
}

export default Header;

关键修改说明

  • queryKey优化:React Query通过queryKey区分不同查询,加入城市参数后,城市变更会自动触发新请求并缓存对应结果。
  • 状态驱动查询:用useState管理城市,状态更新触发组件重渲染,useFetch在顶层接收新参数后自动执行新请求,完全符合Hooks使用规则。
  • 移除DOM直接操作:通过表单事件获取输入值,替代原ref的DOM操作方式,更贴合React的状态管理逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 20:55:34