Home > database >  How to map over a JSON response in React
How to map over a JSON response in React

Time:10-30

Hi I'm trying to learn how to use React with an API response. I have a GraphQL API endpoint that is returning information on products in JSON. I would like to loop over the response and render a react component for each product simply displaying the product name.

The JSON response looks like this:

{
  "data": {
    "products": [
      {
        "productName": "Pepsi",
        "price": "1.99",
      },
      {
        "productName": "Coke",
        "price": "2.99",
      },
      // and so on...
    ]
  }
}  

I've successfully console logged each product name by doing the following (I'm using axios):

async function contactAPI() {
  return await axios({
    url: 'https://graphqlexample.com/api/products',
    method: 'post',
    data: {
      query: `
        QUERY GOES HERE
          `
    }
  })
}

async function goFetch() {
  let resp = await contactAPI();
  for (let entry in resp.data.data.products) {
    console.log(resp.data.data.products[entry]['productName']);
  }  
}

But now I would like to render a react component for each product, but I keep getting the error Objects are not valid as a React child (found: [object Promise]). Below is the code I'm using right now. How can I fix this so that I can return a react component for each product with the product name?

App.js

async function contactAPI() {
  return await axios({
    url: 'https://graphqlexample.com/api/products',
    method: 'post',
    data: {
      query: `
        QUERY GOES HERE
          `
    }
  })
}

async function App() {
  let resp = await contactAPI();
  return (
    <div>
      {resp.map(p => (
        <div>
          <ProductCard productName={p.productName} />
        </div>
      ))}
    </div>
  );
}

ProductCard.js

function ProductCard(props) {
  return (
    <div>
      <div>{props.productName}</div>      
    </div>
  );
}

CodePudding user response:

Since you're using functional components you should implement hooks to 1) get the data, and 2) manage the component state. useEffect to get the data on first render, and useState to store and manage the data that's returned. You can then map over that data stored in the state to create the JSX.

const { useEffect, useState } = React;

function App() {

  // Initialise the state with an empty array
  const [products, setProducts] = useState([]);
  
  // Call `useEffect` with an empty dependency array
  // which will ensure it runs only once
  useEffect(() => {

    // Call the contactAPI function, wait for
    // the data and then update the state with the
    // product array
    async function getData() {
      const res = await contactAPI();
      setProducts(res.data.data.products);
    }
    getData();
  }, []);

  // If the state array is empty show a simple message
  if (!data.length) return <div>No data</div>;

  // Otherwise `map` over the state and produce the JSX
  return (
    <div>
      {products.map(product => (
        <div>
          <ProductCard productName={product.productName} />
        </div>
      ))}
    </div>
  );
}

CodePudding user response:

You should destructure the axios response to get the data, and access the products attribute:

async function App() {
  const { data } = await contactAPI();
  return (
    <div>
      {data.products.map(p => (
        <div>
          <ProductCard productName={p.productName} />
        </div>
      ))}
    </div>
  );
}

Also, you can simplify your axios call like this:

async function contactAPI() {
  return await axios.post('https://graphqlexample.com/api/products', {
      query: `
        QUERY GOES HERE
          `
    }
  )
}

CodePudding user response:

To display the JSON data in React i have used 2 methods. 1.You can make use of class component for fetch it as api. 2.You can import the JSON data file and simply map it.

This is my way of displaying JSON data on React applicatons.

CodePudding user response:

Try modifying your App()---

 async function App() {
  let resp = await contactAPI();
  return (
    <div>
      {resp.data.products.map(p => (
        <div>
          <ProductCard productName={p.productName} />
        </div>
      ))}
    </div>
  );
}
  • Related