tyjanii hassan
tyjanii hassan

Reputation: 65

Changing the state with returned JSON data

i am trying to get data from an external API and use it to change the state on my app. The data actually shows up in the console but when i run set state does not change the state of my app.

class App extends Component {
  state={
    jobs:[]
  }


  onTermSubmit=(term)=>{
    const proxy=`https://cors-anywhere.herokuapp.com/`;
        const api = `${proxy}https://--------/positions.json?description=${term}&page=1`;

    fetch(api).then(res=>res.json()).then(data=>this.setState({jobs:data}))
    console.log(this.state)
  }

I am trying to get the state to change to the data returned from the API

Upvotes: 0

Views: 255

Answers (2)

Shmili Breuer
Shmili Breuer

Reputation: 4147

As mentioned by @Alexander Staroselsky fetch() and setState() are asynchronous operations and the application won't wait until they are done to continue to the next operation thus resulting in this.state.jobs to still be an empty array.

My solution would be to make them synchronous by adding the async/await keyword before calling he function like this.

onTermSubmit= async (term)=> {
    const proxy=`https://cors-anywhere.herokuapp.com/`;
    const api = `${proxy}https://--------/positions.json?description=${term}&page=1`;

    let rawRes = await fetch(api)
    let jsonRes = await rawRes.json()
    await this.setState({jobs:rawRes}))
    console.log(this.state)
}

Just another approach

Hope this is helpful

Upvotes: 0

Alexander Staroselsky
Alexander Staroselsky

Reputation: 38807

Both fetch() and setState() are asynchronous so attempting put a console.log() statement after the expression will not wait for the fetch or setState() to complete/resolve. Instead you can use the callback argument of setState() to console.log() only after fetch has resolved and setState() has updated state. From the documentation:

setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall. Instead, use componentDidUpdate or a setState callback (setState(updater, callback)), either of which are guaranteed to fire after the update has been applied. If you need to set the state based on the previous state, read about the updater argument below.

fetch(api)
  .then(res => res.json())
  .then(data =>
    this.setState({ jobs: data }, () => {
      console.log(this.state);
    })
  )
  .catch(err => console.log(err));

Hopefully that helps!

Upvotes: 3

Related Questions