{HELP ME} Error image.data.attributes.formats.medium is undefined

System Information
  • Strapi Version: v4.8.2
  • Operating System: Kali linux
  • Database: sqlite
  • Node Version: v18.13.0
  • NPM Version: 4.8.2
  • Yarn Version: 1.22.19

I was making an e-commerce website using strapi, react js and i got this error while taking image from strapi database and displaying it to react js page

here’s the json data of strapi

{"data":
[{"id":1,"attributes":{"name":"earbuds","shortDescription":"dummy dummy","longDescription":"_<u>**etsaaaaagesgsegse**</u>_","price":3000,"category":"new","createdAt":"2023-03-21T04:46:53.006Z","updatedAt":"2023-03-22T07:29:55.416Z","publishedAt":"2023-03-21T04:46:56.281Z","image":{"data":{"id":36,"attributes":{"name":"earbuds-prod-3.webp","alternativeText":null,"caption":null,"width":600,"height":600,"formats":{"thumbnail":{"name":"thumbnail_earbuds-prod-3.webp","hash":"thumbnail_earbuds_prod_3_d9ca333eb0","ext":".webp","mime":"image/webp","path":null,"width":156,"height":156,"size":3.54,"url":"/uploads/thumbnail_earbuds_prod_3_d9ca333eb0.webp"},"small":{"name":"small_earbuds-prod-3.webp","hash":"small_earbuds_prod_3_d9ca333eb0","ext":".webp","mime":"image/webp","path":null,"width":500,"height":500,"size":13.88,"url":"/uploads/small_earbuds_prod_3_d9ca333eb0.webp"}},"hash":"earbuds_prod_3_d9ca333eb0","ext":".webp","mime":"image/webp","size":16.85,"url":"/uploads/earbuds_prod_3_d9ca333eb0.webp","previewUrl":null,"provider":"local","provider_metadata":null,"createdAt":"2023-03-21T04:44:43.186Z","updatedAt":"2023-03-21T04:44:43.186Z"}}}}},{"id":2,"attributes":{"name":"speaker","shortDescription":"dssssssssssss","longDescription":"sdfffffffffff","price":5000,"category":"topRated","createdAt":"2023-03-21T04:48:21.908Z","updatedAt":"2023-03-21T04:48:40.165Z","publishedAt":"2023-03-21T04:48:23.291Z","image":{"data":{"id":5,"attributes":{"name":"speaker-prod-3.webp","alternativeText":null,"caption":null,"width":600,"height":600,"formats":{"thumbnail":{"name":"thumbnail_speaker-prod-3.webp","hash":"thumbnail_speaker_prod_3_e91ccd538d","ext":".webp","mime":"image/webp","path":null,"width":156,"height":156,"size":3.5,"url":"/uploads/thumbnail_speaker_prod_3_e91ccd538d.webp"},"small":{"name":"small_speaker-prod-3.webp","hash":"small_speaker_prod_3_e91ccd538d","ext":".webp","mime":"image/webp","path":null,"width":500,"height":500,"size":23.48,"url":"/uploads/small_speaker_prod_3_e91ccd538d.webp"}},"hash":"speaker_prod_3_e91ccd538d","ext":".webp","mime":"image/webp","size":37.8,"url":"/uploads/speaker_prod_3_e91ccd538d.webp","previewUrl":null,"provider":"local","provider_metadata":null,"createdAt":"2023-03-21T04:44:27.785Z","updatedAt":"2023-03-21T04:44:27.785Z"}}}}},{"id":3,"attributes":{"name":"watch","shortDescription":"da","longDescription":"ut","price":2999,"category":"bestSellers","createdAt":"2023-03-21T04:49:18.839Z","updatedAt":"2023-03-22T07:30:25.108Z","publishedAt":"2023-03-21T04:49:20.126Z","image":{"data":{"id":3,"attributes":{"name":"watch-prod-1.webp","alternativeText":null,"caption":null,"width":600,"height":600,"formats":{"thumbnail":{"name":"thumbnail_watch-prod-1.webp","hash":"thumbnail_watch_prod_1_f227af6898","ext":".webp","mime":"image/webp","path":null,"width":156,"height":156,"size":4.11,"url":"/uploads/thumbnail_watch_prod_1_f227af6898.webp"},"small":{"name":"small_watch-prod-1.webp","hash":"small_watch_prod_1_f227af6898","ext":".webp","mime":"image/webp","path":null,"width":500,"height":500,"size":17.47,"url":"/uploads/small_watch_prod_1_f227af6898.webp"}},"hash":"watch_prod_1_f227af6898","ext":".webp","mime":"image/webp","size":21.08,"url":"/uploads/watch_prod_1_f227af6898.webp","previewUrl":null,"provider":"local","provider_metadata":null,"createdAt":"2023-03-21T04:44:27.654Z","updatedAt":"2023-03-21T04:44:27.654Z"}}}}},{"id":4,"attributes":{"name":"earbuds","shortDescription":"dummy dummy","longDescription":"_<u>**etsaaaaagesgsegse**</u>_","price":3000,"category":"new","createdAt":"2023-03-21T15:57:31.141Z","updatedAt":"2023-03-21T16:00:53.862Z","publishedAt":"2023-03-21T15:57:32.587Z","image":{"data":{"id":30,"attributes":{"name":"earbuds-prod-5.webp","alternativeText":null,"caption":null,"width":600,"height":600,"formats":{"thumbnail":{"name":"thumbnail_earbuds-prod-5.webp","hash":"thumbnail_earbuds_prod_5_7325afc56c","ext":".webp","mime":"image/webp","path":null,"width":156,"height":156,"size":2.47,"url":"/uploads/thumbnail_earbuds_prod_5_7325afc56c.webp"},"small":{"name":"small_earbuds-prod-5.webp","hash":"small_earbuds_prod_5_7325afc56c","ext":".webp","mime":"image/webp","path":null,"width":500,"height":500,"size":9.78,"url":"/uploads/small_earbuds_prod_5_7325afc56c.webp"}},"hash":"earbuds_prod_5_7325afc56c","ext":".webp","mime":"image/webp","size":11.9,"url":"/uploads/earbuds_prod_5_7325afc56c.webp","previewUrl":null,"provider":"local","provider_metadata":null,"createdAt":"2023-03-21T04:44:42.720Z","updatedAt":"2023-03-21T04:44:42.720Z"}}}}}],"meta":{"pagination":{"page":1,"pageSize":25,"pageCount":1,"total":4}}}

code i have written

import React, { useEffect, useState } from "react";
import Tabs from "@mui/material/Tabs";
import Tab from "@mui/material/Tab";
import Box from "@mui/material/Box";
import Item from "../../components/Item";
import { Typography } from "@mui/material";
import useMediaQuery from "@mui/material/useMediaQuery";
import { useDispatch, useSelector } from "react-redux";
import { setItems } from "../../state";

const ShoppingList = () => {
  const dispatch = useDispatch();
  const [value, setValue] = useState("all");
  const items = useSelector((state) => state.cart.items);
  const breakPoint = useMediaQuery("(min-width:600px)");

  const handleChange = (event, newValue) => {
    setValue(newValue);
  };

  async function getItems() {
    const items = await fetch(
      "http://localhost:1337/api/items?populate=image",
      { method: "GET" }
    );
    const itemsJson = await items.json();
    dispatch(setItems(itemsJson.data));
  }

  useEffect(() => {
    getItems();
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  const topRatedItems = items.filter(
    (item) => item.attributes.category === "topRated"
  );
  const newArrivalsItems = items.filter(
    (item) => item.attributes.category === "newArrivals"
  );
  const bestSellersItems = items.filter(
    (item) => item.attributes.category === "bestSellers"
  );

  return (
    <Box width="80%" margin="80px auto">
      <Typography variant="h3" textAlign="center">
        Our Featured <b>Products</b>
      </Typography>
      <Tabs
        textColor="primary"
        indicatorColor="primary"
        value={value}
        onChange={handleChange}
        centered
        TabIndicatorProps={{ sx: { display: breakPoint ? "block" : "none" } }}
        sx={{
          m: "25px",
          "& .MuiTabs-flexContainer": {
            flexWrap: "wrap",
          },
        }}
      >
        <Tab label="ALL" value="all" />
        <Tab label="NEW ARRIVALS" value="newArrivals" />
        <Tab label="BEST SELLERS" value="bestSellers" />
        <Tab label="TOP RATED" value="topRated" />
      </Tabs>
      <Box
        margin="0 auto"
        display="grid"
        gridTemplateColumns="repeat(auto-fill, 300px)"
        justifyContent="space-around"
        rowGap="20px"
        columnGap="1.33%"
      >
        { value === "all" &&
          items.map((item) => (
            <Item item={item} key={`${item.name}-${item.id}`} />
          ))}
        {value === "new" &&
          newArrivalsItems.map((item) => (
            <Item item={item} key={`${item.name}-${item.id}`} />
          ))}
        {value === "bestSellers" &&
          bestSellersItems.map((item) => (
            <Item item={item} key={`${item.name}-${item.id}`} />
          ))}
        {value === "topRated" &&
          topRatedItems.map((item) => (
            <Item item={item} key={`${item.name}-${item.id}`} />
          ))}
      </Box>
    </Box>
  );
};

export default ShoppingList;

in item component i have written

import { useState } from "react";
import { useDispatch } from "react-redux";
import { IconButton, Box, Typography, useTheme, Button } from "@mui/material";
import AddIcon from "@mui/icons-material/Add";
import RemoveIcon from "@mui/icons-material/Remove";
import { shades } from "../theme";
import { addToCart } from "../state";
import { useNavigate } from "react-router-dom";

const Item = ({ item, width }) => {
  const navigate = useNavigate();
  const dispatch = useDispatch();
  const [count, setCount] = useState(1);
  const [isHovered, setIsHovered] = useState(false);
  const {
    palette: { neutral },
  } = useTheme();

  const { category, price, name, image } = item.attributes;
  const {
    data: {
      attributes: {
        formats: {
          medium: { url },
        },
      },
    },
  } = image;

  return (
    <Box width={width}>
      <Box
        position="relative"
        onMouseOver={() => setIsHovered(true)}
        onMouseOut={() => setIsHovered(false)}
      >
        <img
          alt={item.name}
          width="300px"
          height="400px"
          src={`http://localhost:1337${url}`}
          onClick={() => navigate(`/item/${item.id}`)}
          style={{ cursor: "pointer" }}
        />
        <Box
          display={isHovered ? "block" : "none"}
          position="absolute"
          bottom="10%"
          left="0"
          width="100%"
          padding="0 5%"
        >
          <Box display="flex" justifyContent="space-between">
            <Box
              display="flex"
              alignItems="center"
              backgroundColor={shades.neutral[100]}
              borderRadius="3px"
            >
              <IconButton onClick={() => setCount(Math.max(count - 1, 1))}>
                <RemoveIcon />
              </IconButton>
              <Typography color={shades.primary[300]}>{count}</Typography>
              <IconButton onClick={() => setCount(count + 1)}>
                <AddIcon />
              </IconButton>
            </Box>
            <Button
              onClick={() => {
                dispatch(addToCart({ item: { ...item, count } }));
              }}
              sx={{ backgroundColor: shades.primary[300], color: "white" }}
            >
              Add to Cart
            </Button>
          </Box>
        </Box>
      </Box>

      <Box mt="3px">
        <Typography variant="subtitle2" color={neutral.dark}>
          {category
            .replace(/([A-Z])/g, " $1")
            .replace(/^./, (str) => str.toUpperCase())}
        </Typography>
        <Typography>name</Typography>
        <Typography fontWeight="bold">price</Typography>
      </Box>
    </Box>
  );
};

export default Item;

I Hope, That anyone will help me, thank you

The simple answer after checking your json file is attached. There is nothing called medium in the response, meaning it’s undefined.

I would suggest using null checks of values or giving it a fallback value. If there is no value your trying to grab fall back to just the URL etc.

so can you rewrite the code please for me

Please note that our Forum and other community channels are primarily meant for community assistance. In this particular situation, @Eventyret has been helpful enough to show you where your issue lies, you will need to take up the task of resolving the issue within your source code with the guidance suggested.