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

React中如何展示天气API数据?是否需用useEffect或事件处理器?

问题解答:React中展示天气API数据的实现方案

你的核心问题是如何展示天气API的数据,以及选择useEffect还是事件处理器。答案很明确:用事件处理器更适合你的场景,因为获取天气是用户点击搜索按钮的主动操作,而useEffect更适合依赖项变化时自动触发的场景(比如页面加载时自动获取默认城市天气)。

下面是具体的实现步骤和修改后的代码:

步骤1:添加天气数据状态

首先需要新增一个状态来存储获取到的天气数据,因为你现在的getWeather函数只是返回数据,没有保存到组件状态中:

const [weather, setWeather] = useState<Forecast | null>(null);

步骤2:修改提交逻辑,保存天气数据

在onSubmit函数中,调用getWeather后把返回的数据存入状态:

const onSubmit = async (e: React.FormEvent) => {
  e.preventDefault();
  if (!town) return;
  // 获取天气数据并更新状态
  const weatherData = await getWeather(town);
  setWeather(weatherData);
  setSearch("");
  setScores([]);
};

步骤3:渲染天气数据

在组件的返回部分,添加天气数据的展示区域,比如在form之后:

{weather && (
  <div className="weather-card">
    <h3>{weather.name}</h3>
    <p>温度:{weather.main.temp}°C</p>
    <p>天气:{weather.weather[0].description}</p>
    <p>湿度:{weather.main.humidity}%</p>
  </div>
)}

完整修改后的代码

import { useEffect, useState } from "react";

import { Town, Forecast } from "./type";

const WEATHER_API_KEY = "API KEY HERE";

export default function SearchCity(): JSX.Element {
  const [search, setSearch] = useState<string>("");
  const [town, setTown] = useState<Town | null>(null);
  const [scores, setScores] = useState<Town[]>([]);
  // 新增天气数据状态
  const [weather, setWeather] = useState<Forecast | null>(null);

  const onSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!town) return;
    // 获取天气并更新状态
    const weatherData = await getWeather(town);
    setWeather(weatherData);
    setSearch("");
    setScores([]);
  };

  const getLocations = async (value: string): Promise<Town[]> => {
    const url = `http://api.openweathermap.org/geo/1.0/direct?q=${value}&limit=3&appid=${WEATHER_API_KEY}`;
    const res = await fetch(url);
    return await res.json();
  };

  const onInputChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const { value } = e.target;
    setSearch(value);
    if (!value) return;
    const locations = await getLocations(value);
    setScores(locations);
  };

  const getWeather = async (town: Town): Promise<Forecast> => {
    const url = `https://api.openweathermap.org/data/2.5/weather?lat=${town.lat}&lon=${town.lon}&units=metric&appid=${WEATHER_API_KEY}`;
    const res = await fetch(url);
    return await res.json();
  };

  const onScoreSelect = (score: Town) => {
    setTown(score);
  };

  useEffect(() => {
    if (town) {
      setSearch(town.name);
      setScores([]);
    }
  }, [town]);

  return (
    <div className="search-container">
      <form onSubmit={onSubmit}>
        <input
          className="input"
          value={search}
          onChange={onInputChange}
          type="text"
          placeholder="Choose a city"
        />
        <button className="submit" type="submit">
          Search
        </button>
        <ul className="list">
          {scores.map((score: Town, index: number) => (
            <li key={index}>
              <button
                className="score-btn"
                onClick={() => onScoreSelect(score)}
              >
                {score.name}
              </button>
            </li>
          ))}
        </ul>
      </form>
      {/* 渲染天气数据 */}
      {weather && (
        <div className="weather-card">
          <h2>{weather.name}</h2>
          <div className="weather-main">
            <img
              src={`https://openweathermap.org/img/wn/${weather.weather[0].icon}@2x.png`}
              alt={weather.weather[0].description}
            />
            <p>{Math.round(weather.main.temp)}°C</p>
          </div>
          <p className="weather-desc">{weather.weather[0].description}</p>
          <div className="weather-details">
            <p>湿度: {weather.main.humidity}%</p>
            <p>风速: {weather.wind.speed} m/s</p>
          </div>
        </div>
      )}
    </div>
  );
}

关于useEffect的补充说明

如果你的需求变成用户选择城市后自动加载天气,不需要点击搜索按钮,那可以用useEffect监听town的变化:

useEffect(() => {
  if (town) {
    const fetchWeather = async () => {
      const data = await getWeather(town);
      setWeather(data);
    };
    fetchWeather();
  }
}, [town]);

这种场景下useEffect就很合适,但回到你的原需求,用户点击搜索才触发,所以事件处理器是更贴合的选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 20:05:55