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

Time:01-31

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

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.

CodePudding user response:

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>
  );
};

CodePudding user response:

First you need to do is export the json and import it on parent and pass the json as props in card.

After that you can map the props json and distribute it on what ever you want.

Using fetch you need to use UseEffect after fetching it store it in useState and pass it on Card component.

  •  Tags:  
  • Related