0

I am trying to write a function that I can reuse to make different fetch requests in my react app. But I am getting unexpected null value and the order in which the function is executed is confusing me. In my code bellow I log the data value before i assign it to my temp variable and which prints the expected output, but the temp variable prints as null - It should also be noted that the temp variable prints BEFORE the data prints even though I have printed the temp variable afterwards... I am calling this function in the componentDidMount() method of the app.js component. Anyone know why I am unable to assign the data from my fetch request to a variable and return it?

  testDynamicAPI(e) {
    var temp;
    fetch(e)
      .then(response => response.json())
      .then(data => { 
        console.log(data);
        temp= data
      });
    console.log(temp);
    return temp;
  }
Dan O
  • 6,022
  • 2
  • 32
  • 50
Tamjid
  • 4,326
  • 4
  • 23
  • 46
  • 1
    Did you try using ``async await`` instead of ``fetch``? – Ajin Kabeer Apr 14 '20 at 04:07
  • 1
    Please see [How do I return the response from an aynchronous call](https://stackoverflow.com/q/14220321/438992), which this duplicates. Although since it's React, you'd just use `setState` like every other React app. Nutshell: you need to understand both async and React a bit more. – Dave Newton Apr 14 '20 at 04:08
  • fetch is asynchronous, hence it depends on the request and response time to print log inside it whereas any method outside fetch including "return temp" will act before fetch finishes executing. Try to put return inside a ".then". Note that if you have multiple then like in your code, is again asynchronous, where each then acts independently. You can separate to different promises and then use promise.all(promise1, promise2).then(.... so on.. – Shoma Apr 14 '20 at 04:21

3 Answers3

1

That's how async code works. Your outer console.log(temp) gets executed before your api finishes its execution. In react, you should make use of setState to manage data with-in your component. To reuse the api function, can return the promise.

...
state = {
    apiData: []
}


testDynamicAPI(e) {
    return fetch(e)
        .then(response => response.json())
}

...
componentDidMount() {
  this.testDynamicApi('/someUrl').then(data => {
            console.log(data);
            this.setState({apiData: data})
        });
  }
}
...
gdh
  • 13,114
  • 2
  • 16
  • 28
  • im not setting the state in this function because i want to return the data here so that i can reuse this function for different api calls. setting state in here wont allow for that :) – Tamjid Apr 14 '20 at 04:22
0

Fetch is an asynchronous API. That means that it is not completed immediately nor blocks untill finished. But once finished it will notify you (the code), while in the meantime other code continues to run.

One way (other than using async/await to do the fetching, see below) is to pass a callback function, which gets called when fetch is finished with the fetched data as argument.

For example:

testDynamicAPI(e, callback) {
    fetch(e)
      .then(response => response.json())
      .then(callback);
  }

You use like:

testDynamicAPI(url, data => console.log(data));

Since fetch returns a promise one can simply also return the fetch and bind subsequent handlers using .then method:

testDynamicAPI(e) {
    return fetch(e)
      .then(response => response.json());
  }

You use like:

testDynamicAPI(url).then(data => console.log(data));

You can also use async / await scheme, like:

async function testDynamicAPI(e) {
    let response = await fetch(e);
    let data = await response.json()
    return data;
}

You use like:

testDynamicAPI(url)
  .then(data => console.log(data)); 
Nikos M.
  • 8,033
  • 4
  • 36
  • 43
0

After running fetch function, return is immediately called while temp is still undefined. As fetch is an async function, it will take its time to do stuffs then callbacks or promise is resolved. You are forgetting the most important part of javascript. you can use async, await like this.

  async testDynamicAPI(e) {
const response=  await fetch(e);

return response.json();

}