Search code examples
javascriptjsonreactjsfetch-api

React: async and await not working with fetch


I have API on Node server returning JSON like this when called:

{"result":[{"ProductID":1,"ProductName":"iPhone10","ProductDescription":"Latest smartphone from Apple","ProductQuantity":100}]}

I'm trying to display all of that information to user using fetch API with React but no matter what my call returns undefined. Here is my React code:

const [products, setProducts] = useState({})

async function getProducts() {
    await fetch(`http://127.0.0.1:5000/listProducts`)
    .then(response => response.json())
    .then(response=>{
      setProducts({products:response.result})
      console.log(response.result);
      products.map(products =>
        <h1>{products.ProductName}</h1>
        <h1>{products.ProductDescription}</h1>
        )
    })
    .catch(err=>console.error(err))
  }

Function getProducts() is called once when page is loaded. What I'm doing wrong? Thanks in advance.


Solution

  • Your function is doing it wrong :

    • The name should be getAndSetProducts or even setProducts / initProducts because it returns a Promise<void> since you don't actually return anything ;
    • You're setting inside products an object { products: Product[] }, I think you want only Product[] (an array of Products) else you'll have to get products by doing products.products ;
    • The map is useless, since you don't do anything with the map response, plus the variable products in the map overwrite the one imported (may cause some errors later).

    Try to do :

    const [products, setProducts] = useState([]); // Array instead of object
    
    async function initProducts() {
        await fetch(`http://127.0.0.1:5000/listProducts`)
            .then(response => response.json())
            .then(response => {
                setProducts(response.result);
                console.log(response.result);
            )
            .catch(err => console.error(err));
    }
    
    function getProductsHtml() {
        return products.map(product =>
            <h1>{product.ProductName}</h1>
            <h1>{product.ProductDescription}</h1>
        );
    }
    

    You can call initProducts when component initialize and return getProductsHtml inside your jsx render.