如何点击搜索按钮后使用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
相关产品推荐
相关产品推荐

