Donc, je suis coincé dans React et ça me fait déjà me gratter la tête ..

J'attrape des données API comme et j'essaie d'accéder à un index ou une boucle en particulier - quoi que je fasse, cela ne semble pas fonctionner!

Voici le composant principal:

class App extends React.Component {
const CityListNames = ['Peterborough', 'Manchester', 'Brighton', 'Liverpool', 'Cardiff'];

  constructor(props) {

    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      items: []
    };

  }

  // Fire our function below on app load
  componentDidMount() {
    this.getWeather();
  }

  // getWeather - make api call
  getWeather = () => {

    let results = [];

    // Loop through our cities list here to gather data 
    // We will then push this into this.state.results
    CityListNames.forEach(function (name) {

      let api_url = "http://api.openweathermap.org/data/2.5/weather?q="+name+",UK&appid="+ApiKey;
      let data;

      // get api data  
      fetch(api_url)
      .then(res => res.json())
      .then(
        (result) => {
          results.push(result); 
          console.log(result[0]);   
        },
        (error) => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      );    

    });    

    this.setState({
      isLoaded: true,
      items: results
    }); 



  }  

  render() {
    const { error, isLoaded, items } = this.state;
    if (error) {
      return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
        <div className="weather-app">

        </div>
      );
    }  
  }
}

export default App;

Lorsque j'utilise console.log(result[0]);, il sort simplement comme "non défini" dans la console.

J'essaie d'attribuer toutes les valeurs à la variable de résultats, puis de la pousser à l'état.

Quand je fais console.log (items), il montre également tous les articles, ce qui est très étrange.

Données API

enter image description here

Toute aide serait grandement appréciée!

Merci

1
Nathan Fitzgerald - Fitzgenius 19 nov. 2018 à 23:59

4 réponses

Meilleure réponse

Vous devez attendre que toutes vos demandes d'api soient résolues avant de définir votre état, donc au lieu d'utiliser forEach, utilisez map et retournez une promesse de la date comme ceci:

getWeather = () => {

    // Loop through our cities list here to gather data 
    // We will then push this into this.state.results
    Promise.all(CityListNames.map(function (name) {

      let api_url = "http://api.openweathermap.org/data/2.5/weather?q="+name+",UK&appid="+ApiKey;

      return fetch(api_url)
      .then(res => res.json());

    })).then((results) => {
      this.setState({
        isLoaded: true,
        items: results
      }); 
    }).catch((error) => {
      this.setState({
        isLoaded: true,
        error
      });
    });
  }  
1
dotconnor 19 nov. 2018 à 21:12

1. chercher: fonctionne de manière asynchrone, donc lorsque vous affectez à l'état la valeur des résultats, ce sera un tableau vide.

this.setState({
        isLoaded: true,
        items: results
      });    

Le code précédent doit aller dans le résultat de la récupération

class App extends React.Component {
cityListNames = ['Peterborough', 'Manchester', 'Brighton', 'Liverpool', 'Cardiff']; // this is one of the changes

  constructor(props) {

    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      items: []
    };

  }

  componentDidMount() {
    this.getWeather();
  }


  getWeather = () => {

    let results = [];

    this.cityListNames.forEach(function (name) { //this is one of the changes

      let api_url = "http://api.openweathermap.org/data/2.5/weather?q="+name+",UK&appid="+ApiKey;
      let data;

      fetch(api_url)
      .then(res => res.json())
      .then((result) => {
          results.push(result); 
          this.setState({ // this is one of the changes
            isLoaded: true,
            items: results
          });    
        },
        (error) => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      );    

    });    

  }  

  render() {
    const { error, isLoaded, items } = this.state;
    if (error) {
      return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
        <div className="weather-app">

        </div>
      );
    }  
  }
}

export default App;
0
Juanes30 19 nov. 2018 à 21:26

Vouliez-vous dire console.log (results [0]) pluriel de 'result'. Dans votre promesse, le résultat est ce que vous obtenez après avoir analysé la réponse à json. Si cette réponse n'a pas de clé de '0' (ce qui ne devrait pas être le cas), alors vous obtiendrez undefined.

Modifier

Le problème n'est pas que vous effectuez un appel asynchrone, puis effectuez l'action synchrone d'un push et console.log. Le problème est qu'il existe une faute de frappe dans laquelle vous enregistrez la console vs appuyez sur la réponse appropriée.

fetch(api_url)
  .then(res => res.json())
  .then(
    (result) => {
      results.push(result); // <--- pushes valid response into array
      console.log(result[0]); // <--- logs undefined   
    },

La réponse n'a pas de clé "0" donc vous vous connectez indéfini, mais vous poussez result (qui est valide). Par conséquent, vous obtiendrez un tableau de résultats corrects à la fin de vos appels. Mais vous enregistrerez un tas de "non définis" sur la console.

1
Sunny Wong 20 nov. 2018 à 15:25

Essaye ça.

class App extends React.Component {
  const CityListNames = ['Peterborough', 'Manchester', 'Brighton', 'Liverpool', 'Cardiff'];
      constructor(props) {

       super(props);
        this.state = {
          error: null,
          isLoaded: false,
          items: []
        };

      }

      // Fire our function below on app load
      componentDidMount() {
        this.getWeather();
      }

      // getWeather - make api call
      getWeather = () => {

        let self = this,
            results = [], responses = [];

        // Loop through our cities list here to gather data 
        // We will then push this into this.state.results
        CityListNames.forEach(function (name) {

          let api_url = "http://api.openweathermap.org/data/2.5/weather?q="+name+",UK&appid="+ApiKey;
          let data;

          // get api data  
          fetch(api_url)
          .then(res => {
             responses.push(res.json());
           });
        };    

        Promise.all(responses).then((values) => {
          self.setState({
            isLoaded: true,
            items: results
          });
        });// this works, because setState is called after before all promises are fulfilled 
      }    

    render() {
      const { error, isLoaded, items } = this.state;
      if (error) {
        return <div>Error: {error.message}</div>;
      } else if (!isLoaded) {
        return <div>Loading...</div>;
      } else {
        return (
          <div className="weather-app">

          </div>
        );
      }  
    }
}

export default App;
1
TuringCreep 19 nov. 2018 à 21:34