使用 react 组件和 useEffect 显示来自 API 的数据

时间:2021-02-08 10:45:25

标签: javascript reactjs api axios

我有这个 react 组件,每次渲染时都会显示通过道具(国家/地区)接收的国家/地区信息,并且使用天气堆栈 API 还必须显示当前时间的首都天气。第一部分(显示来自道具的国家数据)工作正常,但我正在努力从天气 API 获取数据。我在控制台上看到我正在获取当前天气,但无法使用 setState() 将其分配给天气变量,因此我的应用程序崩溃了。

这是我到目前为止的组件代码,我尝试使用 async/await.then 语法以防我拼写错误,但总是得到相同的结果:

const CountryDetails = async ({country}) => {
    
    const [weather, setWeather] = useState({});

    // const hook = async () => {
    //   const result = await axios.get(`http://api.weatherstack.com/current?access_key=${WEATHER_API}&query=${country.capital}`);
    //   console.log(result.data);
    //   setWeather(result.data.current);
    //   console.log(weather);
    // }

    const hook = () => {
      axios.get(`http://api.weatherstack.com/current?access_key=${WEATHER_API}&query=${country.capital}`).then((response) => {
        console.log('then');
        setWeather({
          temperature: response.data.current.temperature,
          img: response.data.current.weather_icons,
          wind: response.data.current.wind_speed,
          dir: response.data.current.wind_direction
        });
        console.log(response.data.current);
      });
    }

    useEffect(hook, []);

    console.log(weather);

    return (
      <>
        <h1>{country.name}</h1>
        <p>capital {country.capital}</p>
        <p>population {country.population}</p>
        <h2>languages</h2>
        <ul>
          {country.languages.map((lang) => {
            <li key={lang.name}>{lang.name}</li>;
          })}
        </ul>
        <img src={country.flag}></img>
        <h2>Weather in {country.capital}</h2>
        <p><b>temperature: </b>{weather.current.temperature}</p>
        <img src={weather.current.weather_icons} />
        <p><b>wind: </b>{weather.current.wind_speed} direction {weather.current.wind_direction}</p>
      </>
    );
  };

包含完整代码的沙盒:https://codesandbox.io/s/vigilant-ride-h3t1j

2 个答案:

答案 0 :(得分:1)

这是我用你的代码创建的一个代码沙盒。既然你说你成功地从 API 接收数据,我用我的 getWeather 函数来嘲笑它。除了@Viet 的回答之外,您提供的代码中还有其他问题。看看这是否有帮助或错误仍然存​​在,请提供代码片段的复制示例:

https://codesandbox.io/s/competent-dhawan-fds81?file=/src/App.js:52-62

import { useEffect, useState } from "react";

const getWeather = (country) => {
  return Promise.resolve({
    data: {
      current: {
        temperature: "<temperature>",
        weather_icons: "<weather_icons>",
        wind_speed: "<wind_speed>",
        dir: "<wind_direction>"
      }
    }
  });
};

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

  const hook = () => {
    getWeather(country).then((response) => {
      console.log("then");
      setWeather({
        temperature: response.data.current.temperature,
        img: response.data.current.weather_icons,
        wind: response.data.current.wind_speed,
        dir: response.data.current.dir,
        wind_speed: response.data.current.wind_speed
      });
      console.log(response.data.current);
    });
  };

  useEffect(hook, [country]);

  // You should get {} logged here, not undefined
  console.log(weather);

  return (
    <>
      <h1>{country.name}</h1>
      <p>Capital: {country.capital}</p>
      <p>Population: {country.population}</p>
      <h2>Languages</h2>
      <ul>
        {/* You were not returning anything in the callback of the map function */}
        {country.languages.map((lang, i) => (
          <li key={i}>{lang.name}</li>
        ))}
      </ul>
      <img src={country.flag}></img>
      <h2>Weather in {country.capital}</h2>
      <p>
        <b>temperature: </b>
        {/* As @Veit mentioned, you were accessing the wrong property */}
        {weather.temperature}
      </p>
      <img src={weather.weather_icons} />
      <p>
        <b>Wind: </b>
        {weather.wind_speed} Direction: {weather.dir}
      </p>
    </>
  );
};

export default (props) => {
  const country = {
    languages: [{ name: "<name>" }],
    flag: "<flag name>",
    capital: "<capital name>",
    name: "<Coutry Name>",
    population: "<POPULATION>"
  };
  return <CountryDetails country={country} />;
};

答案 1 :(得分:0)

您只是从天气状态中提取了错误的属性。这有效:

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

const WEATHER_API = "xxx";

const CountryDetails = ({ country }) => {
  const [weather, setWeather] = useState({});
 
  const hook = () => {
    axios
      .get(
        `http://api.weatherstack.com/current?access_key=${WEATHER_API}&query=${country.capital}`
      )
      .then((response) => {
        console.log("then", response);
        setWeather({
          temperature: response.data.current.temperature,
          img: response.data.current.weather_icons,
          wind: response.data.current.wind_speed,
          dir: response.data.current.wind_dir
        });
        console.log(JSON.stringify(weather));
      });
  };

  useEffect(hook, []);

  console.log(weather);

  return (
    <>
      <h2>languages</h2>
      <p><b>temperature: </b>{weather.temperature}</p>
      <p>
        <b>wind: </b>
        {weather.wind} direction {weather.dir}
      </p>
    </>
  );
};

export default function App() {
  return (
    <div className="App">
      <CountryDetails country={{ capital: "London" }} />
    </div>
  );
}