Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Loading json data with Fetch to pass it to React Component as prop

So I’m struggling with this task for a while and I really can not know what to do.
The problem is when i try to fetch the data from "/menu/items" and then pass it as prop to Card.js I get the information that "Cannot read properties of undefined (reading ‘name’)" in Card.js.

So I have to Components:

Menu.js

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

const Menu = (props) => {
  const [orders, onAddOrder] = useState([]);
  const [menuItems, setMenuItems] = useState([]);

  useEffect(() => {
    getItems();
  });

  const getItems = async () => {
    const response = await fetch("/menu/items");
    const data = await response.json();
    setMenuItems(data);
  };

  return (
    <div className="menu">
      <div className="menu-main__container">
        <article>
          <Card order={menuItems[0]} />
          <Card order={menuItems[1]} />
          <Card order={menuItems[2]} />
        </article>
        <article>
          <Card order={menuItems[3]} />
          <Card order={menuItems[4]} />
          <Card order={menuItems[5]} />
        </article>
        <article>
          <Card order={menuItems[6]} />
          <Card order={menuItems[7]} />
          <Card order={menuItems[8]} />
        </article>
      </div>
    </div>
  );
};

which is parent component of Card Component

Card.js

const Card = (props) => {
  const [order, onAdd] = useState(props.order);

  const onAddOrderHandler = () => {
    console.log(order);
  };

  return (
    <div className="container__order">
      <div className="order__details">
        <img src={KebapImg} className="details__img" />
        <h3>{props.order.name}</h3>
        <p>{props.order.desc}</p>
        <div className="details__price-buy">
          <h1>{props.order.price}zł</h1>
          <input
            type="submit"
            value="Take it!"
            className="price-buy__btn"
          />
        </div>
      </div>
    </div>
  );
};

/menu/items as json file:

{
      id: 1,
      name: "iKebap Pro Max Super",
      price: 22,
      desc: "Lorem Ipsum dolor sit amet, consectetur adipsicing elit",
    },
    {
      id: 2,
      name: "iKebap Pro Max",
      price: 21,
      desc: "Lorem Ipsum dolor sit amet, consectetur adipsicing elit",
    },
    {
      id: 3,
      name: "iKebap Classic",
      price: 15,
      desc: "Lorem Ipsum dolor sit amet, consectetur adipsicing elit",
    },
    {
      id: 4,
      name: "iKebap California Reaper",
      price: 18,
      desc: "Lorem Ipsum dolor sit amet, consectetur adipsicing elit",
    },
    {
      id: 5,
      name: "iKebap Overpriced",
      price: 37,
      desc: "Lorem Ipsum dolor sit amet, consectetur adipsicing elit",
    },
    {
      id: 6,
      name: "iKebap Small",
      price: 10,
      desc: "Lorem Ipsum dolor sit amet, consectetur adipsicing elit",
    },
    {
      id: 7,
      name: "iKebap Wege",
      price: 17,
      desc: "Lorem Ipsum dolor sit amet, consectetur adipsicing elit",
    },
    {
      id: 8,
      name: "iKebap American",
      price: 16,
      desc: "Lorem Ipsum dolor sit amet, consectetur adipsicing elit",
    },
    {
      id: 9,
      name: "iKebap Góralski",
      price: 17,
      desc: "Lorem Ipsum dolor sit amet, consectetur adipsicing elit",
    }

All I want to do is to pass the fetched item to prop and render it as a new component.

>Solution :

First and foremost, add an empty dependency array in the useEffect, cause you don’t wanna run it on every re-render.

useEffect(() => {
    getItems();
}, []);

Second, you are indeed trying to access an undefined property. On first render you are still resolving the fetch. So your menuItems array is still empty, and you’re passing undefined values menuItems[0].

All you need to do is waiting for the next render.

const Menu = (props) => {
  const [orders, onAddOrder] = useState([]);
  const [menuItems, setMenuItems] = useState([]);

  useEffect(() => {
    getItems();
  }, []);

  const getItems = async () => {
    const response = await fetch("/menu/items");
    const data = await response.json();
    setMenuItems(data);
  };

  // ADD THIS LINE
  if (!menuItems.length) return <div>Loading...</div>

  return (
    <div className="menu">
      <div className="menu-main__container">
        <article>
          <Card order={menuItems[0]} />
          <Card order={menuItems[1]} />
          <Card order={menuItems[2]} />
        </article>
        <article>
          <Card order={menuItems[3]} />
          <Card order={menuItems[4]} />
          <Card order={menuItems[5]} />
        </article>
        <article>
          <Card order={menuItems[6]} />
          <Card order={menuItems[7]} />
          <Card order={menuItems[8]} />
        </article>
      </div>
    </div>
  );
};
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading