How to handle asynchronous fetch from Database with Gatsby or React functional component

Viewed 587

I am building a Gatsby app, that's mainly written in React. I have a LoggedIn component where I would grab all books that the user has borrowed and display the status on the website. I use Firebase. I hope that within the LoggedIn component, I can fetch the books. But I am not sure how to wait for the fetch method is done. When I use async/await, it just broke because then my functional component would return a Promise instead of a JSX:ELEMENT type. How can I handle this problem?

import React, { useState } from 'react'
import {fetchUserBook} from "../../firebase/firebaseService"

const LoggedIn = ({user}) => {                //if I put async before user, 
//my LoggedIn component will return a promise, not a JSX component, which will break my code.
  const[books,setBooks] = useState([])
  fetchUserRestaurant(user.email).then((info) => setBooks(info))
    const renderloggedIn = () =>{
        return (
        <>
        <h1>Welcome, {user.email}.</h1>   // I hope that I can pass the "books" props here so that I can render it. 
// But usually the return statement is invoked before my fetchUserRestaurant method finishes. 
        </>
        )
    }
 

    return(
        renderloggedIn()
    )
}

export default LoggedIn
``
1 Answers

You just need to put your async fetch function inside a useEffect hook because it will be triggered once the DOM tree is loaded. Just add:

useEffect(()=>{
  fetchUserRestaurant(user.email).then((info) => setBooks(info))
}, [])

Adding an empty array (deps), will make it will work as a componentDidMount(), since, in a stateless component like yours, you can't use a componentDidMount() lifecycle, you have to use hooks. This will cause a blink content until your request populates your useState hook and it is displayed. You can add a loader or whatever you like if you want to bypass it anyway.

The rest of the code seems correct.

Related