简体   繁体   中英

React don't render a map function of an Axios call

I'm trying to make a shopping cart table in which it shows an image, name of the product and a remove button. I've the id of each product from the localStorage and call all the data of that id with Axios.get(by id).

I'd created a table to show the price, image and name of the product, but my.map function don't show the info in the website (even though I can see it with a console.log). Here is the code:

import Axios from "axios";
import React from "react";

function ClientCardBlock() {
  let memory = window.JSON.parse(localStorage.getItem("toy"));
  console.log(memory); **this log shows me that all the IDs are now in an array**

  const renderItems = () => {
    memory.map(
      async (toy_id) =>
        await Axios.get(`http://************/${toy_id}`).then(
          (response) => {
            const toy = response.data;
            console.log(toy.price); **this log show me the price of each toy, so it's working**
            return (
              <tr key={toy._id}>
                <th>
                  <img
                    alt=""
                    className="card-img-top embed-responsive-item"
                    src={`http://*********/${toy.images}`}
                  />
                </th>
                <th>$ {toy.price}</th>
                <th>
                  <button>Remove</button>
                </th>
              </tr>
            );
          }
        )
    );
  };

  return (
    <div>
      <table className="table table-bordered">
        <thead>
          <tr>
            <th scope="col">Image product</th>
            <th scope="col">Product</th>
            <th scope="col">Remove</th>
          </tr>
        </thead>
        <thead>{renderItems()}</thead>
      </table>
    </div>
  );
}

export default ClientCardBlock;

https://imgur.com/a/bthMJN4

Normally you'd be able to just change it so that renderItems is a functional component.

function RenderItems() {
  return memory.map...(etc)
}

...

<thead><RenderItems /></thead>

but since this is an async function, you need to use a useEffect. This useEffect gets the data and saves it into your component state. Then once it exists, it will render later. The key point is to seperate the fetching from the rendering.

function ClientCardBlock() {
  const [data, setData] = useState([]);

  useEffect(() => {
    /* this runs on component mount */
    const memory = window.JSON.parse(localStorage.getItem("toy"));

    Promise.all(memory.map((toy_id) => Axios
                .get(`http://************/${toy_id}`)
                .then((response) => response.data)))
                /* Wait on the Promise.All */
                .then(newData => {
                  /* Set the data locally */
                  setData(newData);
                });
  }, []);

  return (
    <div>
      <table className="table table-bordered">
        <thead>
          <tr>
            <th scope="col">Image product</th>
            <th scope="col">Product</th>
            <th scope="col">Remove</th>
          </tr>
        </thead>
        <thead>
          {data.map(toy => (
              <tr key={toy._id}>
                <th>
                  <img
                    alt=""
                    className="card-img-top embed-responsive-item"
                    src={`http://*********/${toy.images}`}
                  />
                </th>
                <th>$ {toy.price}</th>
                <th>
                  <button>Remove</button>
                </th>
              </tr>
           )}
        </thead>
      </table>
    </div>
  );
}

export default ClientCardBlock;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM