React:根据所选城市更新天气详细信息的问题

问题描述 投票:0回答:1

我的 React 应用程序遇到问题,无法使用 OpenWeatherMap API 根据所选城市更新天气详细信息。设置如下:

  1. 我有一个父组件

    App
    ,它管理纬度和经度的状态。

  2. App
    内部,我有一个子组件
    DisplayFetch
    ,它根据纬度和经度获取天气详细信息。

  3. 我在

    SearchCities
    内还有另一个子组件
    DisplayFetch
    ,它允许用户搜索城市并在选择城市时更新纬度和经度。

当我在

SearchCities
选择一个新城市时,问题就出现了。虽然
App
组件中的纬度和经度已正确更新,但
DisplayFetch
中显示的天气详细信息不会相应更新。天气详细信息仍与之前的位置相关,而不是更新为新选择的城市的天气。

我已确保

updateLocation
组件中的
App
函数正确更新纬度和经度的状态,并且它被传递到
DisplayFetch
并进一步传递到
SearchCities
。此外,我已经确认,在选择新城市时会调用
update
函数(从
DisplayFetch
传递到
SearchCities
),并且它会正确更新纬度和经度。

应用程序组件:

import React, { useState, useEffect } from "react";
import DisplayFetch from "./components/DisplayFetch";

export default function App() {
  const [latitude, setLatitude] = useState(null);
  const [longitude, setLongitude] = useState(null);

  useEffect(() => {
    navigator.geolocation.getCurrentPosition(
      (position) => {
        console.log(position.coords.latitude);
        console.log(position.coords.longitude);
        setLatitude(position.coords.latitude);
        setLongitude(position.coords.longitude);
      },
      (error) => {
        console.error("Error getting current geolocation:", error);
      }
    );
  }, []);

  const updateLocation = (lat, long) => {
    setLatitude(lat);
    setLongitude(long);
  };

  return (
    <div className="flex items-center justify-center h-screen bg-darkSlate">
      <div>
        {latitude} {longitude}
      </div>
      {latitude !== null && longitude !== null ? (
        <DisplayFetch
          latitude={latitude}
          longitude={longitude}
          updateLocation={updateLocation}
        />
      ) : (
        <p>Loading...dasdasdasdasdas</p>
      )}
    </div>
  );
}

DisplayFetch 组件:

import React, { useState, useEffect } from "react";
import WeatherBox from "./WeatherBox";
import { CiLocationOn } from "react-icons/ci";
import { AsyncPaginate } from "react-select-async-paginate";
import SearchCities from "./SearchCities";

const DisplayFetch = ({ latitude, longitude, updateLocation }) => {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

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

  const fetchData = async () => {
    try {
      const response = await fetch(
        `https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=MYAPI`
      );
      // Replace with your API endpoint
      if (!response.ok) {
        throw new Error("Network response was not ok.");
      }
      const data = await response.json();
      setData(data);
      setLoading(false);
    } catch (error) {
      setError(error.message);
      setLoading(false);
    }
  };
  return (
    <>
      {loading ? (
        <p>Loading...</p>
      ) : error ? (
        <p>Error: {error}</p>
      ) : (
        <div className="bg-paleBlue p-8 rounded-lg shadow-lg flex flex-col">
          <div className="relative border border-solid border-gray-300 rounded-md mb-4">
            <div>
              {latitude} {longitude}
            </div>
            <SearchCities
              latCity={latitude}
              longCity={longitude}
              update={updateLocation} // Pass updateLocation here
            />
            <div className="absolute inset-y-0 right-0 flex items-center pr-2"></div>
          </div>
          <div className="grid grid-cols-2 gap-4">
            <WeatherBox title="Min Temp" value={`${data.main.temp_min}°C`} />
            <WeatherBox title="Max Temp" value={`${data.main.temp_max}°C`} />
            <WeatherBox
              title="Feels Like"
              value={`${data.main.feels_like}°C`}
            />
            <WeatherBox title="Pressure" value={`${data.main.pressure} hPa`} />
            <WeatherBox title="Humidity" value={`${data.main.humidity}%`} />
            <WeatherBox title="Wind Speed" value={`${data.wind.speed} m/s`} />
          </div>
        </div>
      )}
    </>
  );
};

export default DisplayFetch;

搜索城市组件。

import React, { useState, useEffect } from "react";
import { AsyncPaginate } from "react-select-async-paginate";
import { geoApiOptions, GEO_API_URL } from "../components/api";
import DisplayFetch from "./DisplayFetch";

const SearchCities = ({ latCity, longCity, update }) => {
  const [search, setSearch] = useState(null);

  const loadOptions = (inputValue) => {
    return fetch(
      `${GEO_API_URL}/cities?minPopulation=1000&namePrefix=${inputValue}`,
      geoApiOptions
    )
      .then((response) => response.json())
      .then((response) => {
        return {
          options: response.data.map((city) => {
            return {
              value: `${city.latitude} ${city.longitude}`,
              label: `${city.name}, ${city.countryCode}`,
            };
          }),
        };
      });
  };

  const handleOnChange = (searchData) => {
    setSearch(searchData);

    console.log(latCity);
    console.log(longCity);
    if (searchData) {
      const [lat, long] = searchData.value.split(" ");
      update(lat, long);
    } else {
      // Clear the latitude and longitude when no city is selected
      update(null, null);
    }
    console.log(latCity);
    console.log(longCity);
  };
  return (
    <>
      <AsyncPaginate
        placeholder="Search for city"
        debounceTimeout={600}
        value={search}
        onChange={handleOnChange}
        loadOptions={loadOptions}
      />
      <>
        <div>
          {latCity} from search city{longCity}
        </div>
      </>
    </>
  );
};

export default SearchCities;

有人能找到我哪里出错了吗?我似乎找不到问题

javascript reactjs react-hooks jsx state-management
1个回答
0
投票

看起来您缺少 useEffect 中的依赖项数组。

 useEffect(() => {
  fetchData();
 }, [latitude, longitude, updateLocation]);
© www.soinside.com 2019 - 2024. All rights reserved.