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

React项目中OpenWeather API温度单位切换参数传递问题

问题分析与解决方案

你的核心问题有两个:

  1. units状态未设置初始值,首次请求时URL中的units参数会是undefined,导致API返回默认单位(开尔文)
  2. 切换单位时没有触发API重新请求,只有点击搜索按钮才会获取数据,所以温度不会自动更新

修改步骤

1. 给units设置默认值

初始化units为一个有效值(比如"metric",对应摄氏度),确保首次请求时参数合法:

const [units, setUnits] = useState("metric");

2. 重构apiCall函数,使其可复用

把原来依赖表单事件的apiCall改成接收城市名和单位作为参数,方便切换单位时调用:

const apiCall = async (cityName, unitType) => {
  const url = `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=${apiKey}&units=${unitType}`;
  const res = await axios.get(url);
  
  setWeather({
    descp: res.data.weather[0].description,
    temp: res.data.main.temp,
    city: res.data.name,
    humidity: res.data.main.humidity,
    wind: res.data.wind.speed,
    feel: res.data.main.feels_like,
  });
  
  setCity(res.data.name);
};

3. 更新表单提交逻辑

修改表单的onSubmit事件,调用重构后的apiCall并传入输入的城市和当前单位:

<form onSubmit={(e) => {
  e.preventDefault();
  const loc = e.target.elements.loc.value;
  if (loc.trim()) { // 避免空输入
    apiCall(loc, units);
  }
}}>

4. 让单位切换触发API请求

修改SegmentedControl的onChange事件,更新units状态的同时,如果已经搜索过城市(即city有值),就重新调用API获取对应单位的天气数据:

<SegmentedControl
  value={units}
  onChange={(newUnits) => {
    setUnits(newUnits);
    // 已有城市数据时,重新请求对应单位的天气
    if (city) {
      apiCall(city, newUnits);
    }
  }}
  data={[
    {
      value: "standard",
      label: (
        <Center>
          <Box>Kelvin</Box>
        </Center>
      ),
    },
    {
      value: "metric",
      label: (
        <Center>
          <Box>Celsius</Box>
        </Center>
      ),
    },
    {
      value: "imperial",
      label: (
        <Center>
          <Box>Fahrenheit</Box>
        </Center>
       ),
    },
  ]}
/>

5. 优化天气状态初始值(可选)

把weather的初始状态从空字符串改为null,语义更清晰:

const [weather, setWeather] = useState(null);

修改后的完整关键代码片段

export default function Home() {
  const [weather, setWeather] = useState(null);
  const [city, setCity] = useState("");
  const [units, setUnits] = useState("metric"); // 设置默认单位

  // 重构后的apiCall函数
  const apiCall = async (cityName, unitType) => {
    const url = `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=${apiKey}&units=${unitType}`;
    const res = await axios.get(url);
    
    setWeather({
      descp: res.data.weather[0].description,
      temp: res.data.main.temp,
      city: res.data.name,
      humidity: res.data.main.humidity,
      wind: res.data.wind.speed,
      feel: res.data.main.feels_like,
    });
    
    setCity(res.data.name);
  };

  const Weath = () => {
    return (
      <div className="container">
        <div>
          <div>
            <Text mr="xs">Units:</Text>
            <SegmentedControl
              value={units}
              onChange={(newUnits) => {
                setUnits(newUnits);
                if (city) {
                  apiCall(city, newUnits);
                }
              }}
              data={[
                {
                  value: "standard",
                  label: (
                    <Center>
                      <Box>Kelvin</Box>
                    </Center>
                  ),
                },
                {
                  value: "metric",
                  label: (
                    <Center>
                      <Box>Celsius</Box>
                    </Center>
                  ),
                },
                {
                  value: "imperial",
                  label: (
                    <Center>
                      <Box>Fahrenheit</Box>
                    </Center>
                   ),
                },
              ]}
            />
          </div>
        </div>
        {/* 其余渲染代码保持不变 */}
      </div>
    );
  };

  return (
    <div className="app">
      <div className="search">
        <form onSubmit={(e) => {
          e.preventDefault();
          const loc = e.target.elements.loc.value;
          if (loc.trim()) {
            apiCall(loc, units);
          }
        }}>
          <input type="text" placeholder="city" name="loc" />
          <button className="bttn">Search</button>
        </form>

        {weather && <Weath />}
      </div>
    </div>
  );
}

这样修改后,点击单位切换按钮时,只要已经搜索过城市,就会自动重新请求对应单位的天气数据,温度会随之更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 02:34:51