如何使用来自 API 的响应数据在 React UseEffect 中调用另一个不同的 API 请求?

时间:2021-07-15 01:27:26

标签: reactjs api use-effect

我想知道如何调用需要来自其他 API 的数据的 API。就我而言,我想获取坐标;纬度和经度,并使用这些进行另一个 API 调用以检索我需要的信息。

这是 App.js 文件

import React from 'react';
import './App.css';
import CityInput from "./components/CityInput";
import {Container} from 'react-bootstrap';
import UseFetch from "./hooks/useFetch";
import {API_BASE_URL, API_KEY} from "./apis/config";
import WeatherList from "./components/WeatherList";

const App = () => {
    const {data, error, isLoading, setUrl} = UseFetch();

    const getContent = () => {
        if(error) return <h2>Error when fetching: {error}</h2>
        if(!data && isLoading) return <h2>LOADING...</h2>
        if(!data) return null;
        return <WeatherList weathers={data.list}/>
    };

    return (
      <Container className="App">
          {/* user types a city and clicks search*/}
          <CityInput onSearch={(city) => setUrl(`${API_BASE_URL}/data/2.5/forecast?q=${city}&appid=${API_KEY}&units=metric`)} />

          {getContent()}

      </Container>
    );
}

export default App;

这是我的 UseFetch.js 文件

import {useState, useEffect} from 'react';
import {API_BASE_URL, API_KEY} from "../apis/config";

const UseFetch = (initialUrl) => {
    const [data, setData] = useState(null);
    const [error, setError] = useState(null);
    const [isLoading, setIsLoading] = useState(null);
    const [url, setUrl] = useState(initialUrl);

    useEffect(() => {
        if(!url) return;
        setIsLoading(true);
        setData(null);
        setError(null);

        fetch(url)
            .then((response) => response.json())
            .then((data) => {
                setIsLoading(false);
                if(data.cod >= 400) {
                    setError(data.message);
                    return;
                }
                setData(data);
                console.log(data);

                console.log(data.city.coord.lat);
                console.log(data.city.coord.lon);


            })
            .catch((error) => {
                setIsLoading(false);
                setError(error);
            });
        //
        // console.log('HIIIIII'+ data);
        // fetch(`${API_BASE_URL}/data/2.5/onecall?lat=${data.city.coord.lat}&lon=${data.city.coord.lon}&exclude=minutely&appid=${API_KEY}`)
        //     .then((response) => response.json())
        //     .then((data2) =>  {
        //         setIsLoading2(false);
        //         setData2(data2);
        //         console.log(data2);
        //     })
        //     .catch((error2) => {
        //         setIsLoading2(false);
        //         setError2(error);
        //     });
    }, [url]);
    return { data, error, isLoading, setUrl};


};

export default UseFetch;

我想检索纬度和经度,以便我可以再次获取

fetch(`${API_BASE_URL}/data/2.5/onecall?lat=${data.city.coord.lat}&lon=${data.city.coord.lon}&exclude=minutely&appid=${API_KEY}`)

但这似乎不起作用。 我正在使用这些 API 作为参考:

https://openweathermap.org/forecast5

https://openweathermap.org/api/one-call-api

2 个答案:

答案 0 :(得分:0)

在 Initial Api 发送回响应后立即调用它,例如:

fetch(APIURL)
.then(response => {
/** do any operations using received response data **/

/** Calling second api **/
fetch(API_URL_ + response.data.url)
.then(data => {
setData(data)
})
.catch(error)
}).catch(error)

UseFetch.js

import {useState, useEffect} from 'react';
import {API_BASE_URL, API_KEY} from "../apis/config";

const UseFetch = (initialUrl) => {
    const [data, setData] = useState(null);
    const [error, setError] = useState(null);
    const [isLoading, setIsLoading] = useState(null);
    const [url, setUrl] = useState(initialUrl);

    useEffect(() => {
        if(!url) return;
        setIsLoading(true);
        setData(null);
        setError(null);

        fetch(url)
            .then((response) => response.json())
            .then((data) => {
                setIsLoading(false);
                if(data.cod >= 400) {
                    setError(data.message);
                    return;
                }
                setData(data);
                console.log(data);

                console.log(data.city.coord.lat);
                console.log(data.city.coord.lon);

  console.log('HIIIIII'+ data);
fetch(`${API_BASE_URL}/data/2.5/onecall?lat=${data.city.coord.lat}&lon=${data.city.coord.lon}&exclude=minutely&appid=${API_KEY}`)
             .then((response) => response.json())
             .then((data2) =>  {
                 setIsLoading2(false);
                 setData2(data2);
                 console.log(data2);
             })
             .catch((error2) => {
                 setIsLoading2(false);
                 setError2(error);
            });

            })
            .catch((error) => {
                setIsLoading(false);
                setError(error);
            });
        
    }, [url]);
    return { data, error, isLoading, setUrl};


};

export default UseFetch;

答案 1 :(得分:0)

在将第一个响应保存在变量中后,您可以尝试链接另一个 .then()?类似:

let anyVariable;
        
       fetch(url)
        .then((response) => response.json())
        .then((data) => {
            setIsLoading(false);
            if(data.cod >= 400) {
                setError(data.message);
                return;
            }
            anyVariable = data.city.coord
        })
        .then(() => {
            fetch(`${API_BASE_URL}/data/2.5/onecall?lat=${anyVariable.lat}&lon=${anyVariable.lon}&exclude=minutely&appid=${API_KEY}`)
         .then((response) => response.json())
         .then((data2) =>  {
             setIsLoading2(false);
             setData2(data2);
             console.log(data2);
         })

        })

无论如何,我认为使用 axios 和 async await 会更干净、性能更好。还要注意 useState 是异步的。