0

I am trying to get the return value of fetch call and pass it as a prop to another react component. The issue i am having is the function returns as undefined.

render() {
function getUserWhoPosted (id){
let url = new URL('http://10.6.254.22:5000/userinformation' + '/'+ id)
fetch(url).then((resp) => resp.json()) // Transform the data into json
.then((data) => {
  console.log(data[0].firstName)
  return data[0].firstName
})
}

//  console.log(getUserWhoPosted(1))


const reversedProps = this.props.posts.reverse();
const postItems = reversedProps.map(post => (
  // console.log(getUserWhoPosted(post.userId)),
  <PostBodyTemplate key={post.id} title={post.title} postBody={post.postBody} giphyUrl = 
  {post.giphyUrl} userWhoPosted = { getUserWhoPosted(post.userId) }/>
  ));

 return (
  <div>
     <h1>{postItems}</h1> 
  </div>
 )
 }

getUserWhoPosted(post.userId) should return a name, it returns as undefined.

EzJS
  • 219
  • 1
  • 4
  • 12

1 Answers1

0

Actually, getUserWhoPosted doesn't return anything (which by default means it's undefined); it's the callback function inside your .then which returns something. But that doesn't bubble up to the main function; the only use of returning something from a .then handler is to pass a value to the next .then in the chain... which there is none in this case.

Fetch is asynchronous. It returns a Promise, then the rest of your code continues before the fetch has actually gotten any data. When the data finally comes in, the .then handler will be called and passed the data. The code won't wait for this to happen.

Instead, what you should do is create a variable outside your Promise (let's call it userWhoPosted) and pass THAT as the prop value. And instead of returning data[0].firstName in your Promise handler, just set the value of userWhoPosted to that. That should do what you want; userWhoPosted will be undefined until the data comes in, at which point it will be set to the result of the fetch.

IceMetalPunk
  • 5,476
  • 3
  • 19
  • 26
  • 2
    A global variable won't change anything on the asynchronous behavior of `fetch()`. Especially not in this case where `getUserWhoPosted()` is called in a `.map()` callback. – Andreas Oct 09 '19 at 16:44
  • I did a return before the fetch so now it works. The issue i am having now is that when passed in the component it says Objects are not valid as React Child. When i try to turn it into a string i get [Object Promise] as the string. – EzJS Oct 09 '19 at 17:03
  • @Andreas I wasn't suggesting it would change the async behavior, I was suggesting it as a global scope variable that could hold the value once the async fetch was done. I did miss the part where this is being called in a map, though; still, a global object mapping IDs to the results could work the same way as a global variable might. – IceMetalPunk Oct 09 '19 at 17:44
  • @EzJS Yes, because again, fetch returns a Promise, which runs on its own and the rest of your code won't wait for it. Your return inside the `then` handler doesn't actually return any values up where you think it is. You cannot return directly from an asynchronous function like fetch, you have access to the results only inside the callbacks unless you explicitly set more global variables to those values at that point. Or use async/await, but you can't use that in a map callback like you're trying to do anyway. – IceMetalPunk Oct 09 '19 at 17:45
  • Once again. Global variables won't help. Just read the dupe target and the linked questions in the accepted answer for the _why_ – Andreas Oct 09 '19 at 18:33
  • @Andreas I understand what asynchronous means. Global variables are still a potential solution and would work fine, even if they're not the best solution. For instance: `const result = null; doAsyncThing().then(res => { result = res; })` . Now the value of `result` in global scope will be null until the Promise resolves, and then it will be set to the value it resolved with. What part of that would stop the result variable from either updating when the Promise resolves or being accessible outside the callback scope? – IceMetalPunk Oct 09 '19 at 18:42