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

React TypeScript天气应用搜索栏报错:无法读取undefined的'name'属性

天气应用搜索栏报错与数据更新问题解决

错误原因

  • Inputs组件中,weather状态被同时用来存储API返回的天气对象和搜索框的字符串值。当按下退格键时,setWeather(e.currentTarget.value)把weather变成了字符串,此时再访问weather.location.name自然会抛出Cannot read properties of undefined (reading 'name')错误。
  • App和Inputs组件各自维护独立的weather状态,导致搜索后的数据无法同步到App组件展示。

修复后的代码

App.tsx

将天气状态统一在App组件管理,提供更新天气的方法给Inputs组件,移除重复的getWeather函数:

import { useEffect, useState } from "react";
import { ReactComponent as Logo } from "../src/mag-glass.svg";
import "./App.css";

import Inputs from "./components/Inputs";
import TemperatureAndDetails from "./components/TemperatureAndDetails";
import TimeAndLocation from "./components/TimeAndLocation";

function App() {
  const [weather, setWeather] = useState<any>();
  const [loading, setLoading] = useState(true);

  // 统一获取天气数据的函数
  async function getWeather(city: string = "London") {
    setLoading(true);
    try {
      const response = await fetch(
        `https://api.weatherapi.com/v1/current.json?key=462eaa5d277d46b0957222907232503&q=${city}&aqi=no`
      );
      const data = await response.json();
      setWeather(data);
    } catch (err) {
      console.error("获取天气失败:", err);
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    getWeather();
  }, []);

  if (loading) {
    return <p>loading</p>;
  }

  return (
    <div className="App">
      <header className="App-header"></header>
      {/* 把getWeather传递给Inputs,用于搜索新城市 */}
      <Inputs onSearch={getWeather} currentCity={weather.location.name} />
      <TimeAndLocation />
      <h1>Weather in {weather.location.name}</h1>
      <h1 id="temp-display">{weather.current.temp_f}&deg;F</h1>
      <TemperatureAndDetails />
      <h1>Feels Like: {weather.current.feelslike_f}&deg;F</h1>
      <h1>Humidity: {weather.current.humidity}%</h1>
      <h1>Wind Speed: {weather.current.gust_mph} mph</h1>
    </div>
  );
}

export default App;

Inputs.tsx

单独维护搜索输入框的状态,不再复用weather对象,通过props接收父组件的搜索方法和当前城市:

import React, { useState } from "react";
import { GrLocation } from "react-icons/gr";
import { AiOutlineSearch } from "react-icons/ai";

// 定义props类型
type InputsProps = {
  onSearch: (city: string) => void;
  currentCity: string;
};

function Inputs({ onSearch, currentCity }: InputsProps) {
  const [searchQuery, setSearchQuery] = useState(currentCity);

  const handleSearch = () => {
    if (searchQuery.trim()) {
      onSearch(searchQuery.trim());
    }
  };

  // 按回车键触发搜索
  const handleKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Enter") {
      handleSearch();
    }
  };

  return (
    <div>
      <div id="search-container">
        <AiOutlineSearch onClick={handleSearch} />
        <input
          id="search-bar"
          type="text"
          placeholder="Search.."
          value={searchQuery}
          onChange={(e) => setSearchQuery(e.currentTarget.value)}
          onKeyPress={handleKeyPress}
        />
        <GrLocation />
        <div className="temperature">
          <button name="imperial" id="fahrenheit-button">
            &deg;F
          </button>
          <p>|</p>
          <button name="metric" id="celcius-button">
            &deg;C
          </button>
        </div>
      </div>
    </div>
  );
}

export default Inputs;

关键改进点

  • 状态提升:把天气数据的状态统一放在App组件管理,Inputs组件只负责搜索输入和触发搜索,避免状态分散导致的数据不同步。
  • 分离状态职责:Inputs组件用searchQuery专门存储输入框的值,不再混用API返回的对象,彻底解决退格时的类型错误。
  • 统一数据获取:把getWeather函数放在App组件,通过props传递给Inputs,确保搜索新城市后能更新App的天气状态,从而展示新数据。
  • 增加错误处理:在getWeather中加入try/catch,处理网络请求失败的情况。
  • 优化交互:增加回车键触发搜索的功能,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 02:15:43