3

I got chained axios call to different API's. When i console.logging state inside function, i am getting updated state. However, when i am console.logging in render() method i am not getting updated state.

Function is fired off after submit button is clicked, so the component is being re-rendered in my opinion.

App.js

import React, { Component } from 'react';
import './App.css';

import axios from 'axios';

import CitySearchForm from './CitySearchForm/CitySearchForm';
import CityOutput from './CityOutput/CityOutput';

class App extends Component {
 state = {
  country: '',
  error: false,
  cities: []
 }

getCities = (e) => {
e.preventDefault();

const countryName = e.target.elements.country.value.charAt(0).toUpperCase() + e.target.elements.country.value.slice(1);

const countryUrl = 'https://api.openaq.org/v1/countries';
const wikiUrl ='https://en.wikipedia.org/w/api.php?action=query&prop=extracts&exintro&explaintext&format=json&category=city&redirects&origin=*&titles=';


axios
.get(countryUrl)
.then( response => {
  const country = response.data.results.find(el => el.name === countryName);
  return axios.get(`https://api.openaq.org/v1/cities?country=${country.code}&order_by=count&sort=desc&limit=10`)
})
.then( response => {
  const cities = response.data.results.map(record => {
    return { name: record.city };
  });
  cities.forEach(city => {
     axios
    .get(wikiUrl + city.name)
    .then( response => {
      let id;
      for (let key in response.data.query.pages) {
        id = key;
      }
      const description = response.data.query.pages[id].extract;
      this.state.cities.push({ city: `${city.name}`, description })
    })
  })
})
.catch(error => { 
  console.log('oopsie, something went wrong', error)
 })
}

render () {
console.log(this.state.cities)
return (
  <div className="App">
    <CitySearchForm getCities={this.getCities} getInformation={this.getInformation}/>
    {this.state.cities.forEach( item => {
      item.map(({ city, description }) => (
        <CityOutput 
        city={city}
        description={description} />
      ))
    })}
  </div>
  );
 }
}

export default App;

2 Answers 2

2

You should never try to directly modify state in React. So this line

this.state.cities.push({ city: `${city.name}`, description })

won't work. Instead, access the previous state by passing a function to setState and modify that:

this.setState(prevState => ({
   cities: [...prevState.cities, { city: `${city.name}`, description }]
}))
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much, it was my silly mistake that i haven't noticed that i was not updating state...Both solutions worked, but i sticked with Iarz one, since i am not working on original array.
2

In React you should set state instead of trying to push values into an array that's is part of the state

change:

this.state.cities.push({ city: `${city.name}`, description })

to something like:

const {cities} = this.state;
cities.push({ city: `${city.name}`, description });
this.setState(cities);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.