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

React中useEffect调用数据问题:农场天气API参数undefined报错

问题:调用OpenWeatherMap API时出现400错误(lat/lon为undefined)

我尝试通过农场的经纬度获取天气数据,已经成功从API拿到农场数据并传入React组件,但调用OpenWeatherMap接口时一直报错:
GET http://api.openweathermap.org/data/2.5/weather?lat=undefined&lon=undefined&appid=[API]&units=metric 400 (Bad Request)

相关代码

FarmDetails组件

import React, { useState, useEffect } from "react";
import { Link, useNavigate, useParams } from "react-router-dom";
import Menubar from "../../components/menubar/Menubar";
import Skeleton from "react-loading-skeleton";
import toast, { Toaster } from 'react-hot-toast';
import axios from 'axios';

import { LazyLoadImage } from "react-lazy-load-image-component";
import Weather from "../../components/weather/Weather";
import FarmWeather from "../../components/weather/FarmWeather";


function FarmDetails() {
    let navigate = useNavigate();
    const [farm, setFarm] = useState('');
    const { username } = useParams();
    const { farmId } = useParams();
    const [isLoading, setIsLoading] = useState(true);

    useEffect(() => {

        let isMounted = true;

        axios.get(`/api/farm/${username}/${farmId}`).then(res => {
            if (isMounted) {
                if (res.data.status === 200) {
                    setFarm(res.data.farm);
                    setIsLoading(false);
                    console.warn(res.data.farm)
                }
                else if (res.data.status === 404) {
                    navigate('/');
                    toast.error(res.data.message, "error");
                }
            }

        });

        return () => {
            isMounted = false
        };
    }, []);


    return (
        <div>
            <Menubar />
            <div className="appHeader bg-primary text-light">
                <div className="left">
                    <a onClick={() => navigate(-1)} className="headerButton goBack">
                        <i className="fi fi-rr-angle-left"></i> </a>
                </div>
                <div className="pageTitle">{farm.farmname}</div>
                <div className="right"></div>
            </div>
            <div id="appCapsule">
                <div className="section mt-3 mb-3">
                    <div className="card">
                        <div className="card-header">
                            Discover
                        </div>
                        <div className="card-body">
                            <h5 className="card-title">Farm Supplies</h5>
                            <p className="card-text">Order for farm supplies suitable for your farm and grow healthy fruits</p>
                            <a href="shop.php" className="btn btn-primary spinner-btn">Go to Shop</a>
                        </div>

                    </div>

                </div>

                <FarmWeather farm={farm} />

                <div className="section mt-3 mb-3">
                    <div className="row">
                        <div className="col-6">

                            <div className="card card-normal">
                                <div className="card-body">
                                    <h5 className="card-title title-small mb-2">Location</h5>
                                    <div className="card-icon mb-0">
                                        <i className="fi fi-rr-marker"></i>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <div className="col-6">

                            <div className="card card-normal card-add">
                                <a href="farm-fruits.php?view=<?php echo $row['farmid']; ?>">
                                    <div className="card-body">
                                        <h5 className="card-title title-small mb-2">Fruits</h5>
                                        <div className="card-icon mb-0">
                                            <i className="fi fi-rr-apple-whole"></i>
                                        </div>
                                    </div>
                                </a>
                            </div>
                        </div>

                        <div className="col-6">

                            <div className="card card-normal">
                                <div className="card-body">
                                    <h5 className="card-title title-small mb-2">Sales</h5>
                                    <div className="card-icon mb-0">
                                        <i className="fi fi-rr-bolt"></i>
                                    </div>
                                </div>
                            </div>


                        </div>

                        <div className="col-6">

                            <div className="card card-normal">
                                <div className="card-body">
                                    <h5 className="card-title title-small mb-2">Expenses</h5>
                                    <div className="card-icon mb-0">
                                        <i className="fi fi-rr-settings"></i>
                                    </div>
                                </div>
                            </div>


                        </div>

                    </div>
                </div>
            </div>



        </div>
    );
}
export default FarmDetails;

FarmWeather组件

import React, { useState, useEffect } from "react";


const FarmWeather = ({ farm }) => {

    const [weather, setWeather] = useState({});

    useEffect(() => {
        fetch(`//api.openweathermap.org/data/2.5/weather?lat=${farm.latitude}&lon=${farm.longitude}&appid=[API]&units=metric`)
            .then((result) => result.json())
            .then((weather) => {
                setWeather(weather);
            });
    }, []);

    console.warn("result", weather)

    return (
        <div className="section mt-3 mb-3">
            <div className="card text-white bg-primary mb-2">
                <div className="card-header">Weather in <span>{weather.name}</span>
                    <div className="weather-icon">
                        <img src={`http://openweathermap.org/img/w/${weather.weather && weather.weather[0].icon}.png`} alt="weather icon" />
                    </div>
                </div>
                <div className="card-body">
                    <h5 className="card-title">Temp <span>{weather.main && weather.main.temp} &deg;C</span></h5>
                    <p className="card-text">Our Technologies have discovered that the Current Weather around your Farm in {farm.county && farm.county.countyname} is
                        Mostly
                        <span id="description" ></span>
                    </p>
                </div>
            </div>
        </div>
    );
}
export default FarmWeather;

问题原因

  1. 初始状态错误:FarmDetails中farm的初始值是空字符串'',组件挂载时FarmWeather接收的farm是字符串,访问farm.latitude和farm.longitude会得到undefined。
  2. Effect依赖缺失:FarmWeather的useEffect依赖数组为空,只会执行一次,此时农场数据还未从API加载完成,导致拼接URL时使用了undefined的经纬度。

解决方案

1. 修正farm初始状态

在FarmDetails组件中,将farm的初始状态改为空对象,避免访问字符串属性出错:

const [farm, setFarm] = useState({});

2. 给Effect添加正确依赖并增加校验

修改FarmWeather的useEffect,添加经纬度作为依赖,并在调用API前校验经纬度是否存在,避免无效请求:

useEffect(() => {
  // 确保经纬度存在再发起请求
  if (farm.latitude && farm.longitude) {
    fetch(`//api.openweathermap.org/data/2.5/weather?lat=${farm.latitude}&lon=${farm.longitude}&appid=[API]&units=metric`)
      .then((result) => result.json())
      .then((weather) => {
        setWeather(weather);
      });
  }
}, [farm.latitude, farm.longitude]);

3. 可选:添加条件渲染优化体验

利用FarmDetails中的isLoading状态,在农场数据加载完成前不渲染FarmWeather:

// 在FarmDetails的return中替换原<FarmWeather/>代码
{!isLoading && <FarmWeather farm={farm} />}

或者在FarmWeather中添加加载状态提示:

const FarmWeather = ({ farm }) => {
    const [weather, setWeather] = useState({});

    useEffect(() => {
        if (farm.latitude && farm.longitude) {
            fetch(`//api.openweathermap.org/data/2.5/weather?lat=${farm.latitude}&lon=${farm.longitude}&appid=[API]&units=metric`)
                .then((result) => result.json())
                .then((weather) => {
                    setWeather(weather);
                });
        }
    }, [farm.latitude, farm.longitude]);

    // 经纬度未加载时显示提示
    if (!farm.latitude || !farm.longitude) {
        return <div className="section mt-3 mb-3"><div className="card text-white bg-primary mb-2"><div className="card-body">加载天气数据中...</div></div></div>;
    }

    return (
        // 原渲染代码
    );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 11:05:26