0

I have an ECommerce project, and this project contains the operations of displaying products, creating a product, deleting a product, and displaying a specific product information.

And my problem is only in displaying the data.

Where through the App file, the data is fetched from the backend and passed to the component "Products" and then displayed on the interface.

The problem is that the data was fetched from the backend and the data coming from the backend appeared in the browser and the request succeeded, but the problem is that the data was not displayed on the interface, and the interface was completely empty.

How can I solve this problem?

App.js:

import * as React from "react";
import Navbar from "./Navbar";
import Products from "./Products";
import { getAllProducts } from "../services/ECommerceServices";

const App = () => {
  console.log("Hi in App file");
  //   const [products, setProducts] = React.useState([]);

  const getAllProductsFun = () => {
    console.log("Hi I am in App file get all products");
    getAllProducts().then((products) => {
      //   console.log(products);
      //   setProducts(products);
      console.log("pppppppppppp: ", products);
      return products;
    });
  };

  return (
    <>
      <Navbar />
      <Products getAllProductsFun={getAllProductsFun} />
    </>
  );
};

export default App;

products.js:

import * as React from "react";
import { styled } from "@mui/material/styles";
import Box from "@mui/material/Box";
import Paper from "@mui/material/Paper";
import Grid from "@mui/material/Grid";
import { makeStyles } from "@mui/styles";
import { Typography } from "@mui/material";
import Head from "next/head";
import useMediaQuery from "@mui/material/useMediaQuery";
import { useTheme } from "@mui/material/styles";
import Dialog from "./Dialog";
import Product from "./Product";
import { getAllProducts } from "../services/ECommerceServices";

const Item = styled(Paper)(({ theme }) => ({
  backgroundColor: theme.palette.mode === "dark" ? "#1A2027" : "#fff",
  ...theme.typography.body2,
  padding: theme.spacing(1),
  textAlign: "center",
  color: theme.palette.text.secondary,
}));

const useStyles = makeStyles({
  main: {
    padding: "4rem ",
  },
  typo: {
    color: "#ffc400 !impoertant",
  },
  // button: {
  //   textTransform: "none !important",
  //   backgroundColor: "#ffc400 !important",
  //   color: "white  !important",
  //   padding: 14,
  // },
});

function Products({ getAllProductsFun }) {
  console.log("check: ", getAllProductsFun);
  const theme = useTheme();
  const breakpoint = useMediaQuery(theme.breakpoints.down("sm"));

  return (
    <>
      <Head>
        <title>Solek</title>
      </Head>
      <Grid
        container
        direction={breakpoint ? "column" : "row"}
        style={{ margin: "4rem" }}
      >
        <Grid item xs={12} sm={9} md={9}>
          <Typography
            variant="h4"
            gutterBottom
            component="div"
            // className={classes.typo}
            style={{ fontWeight: 600 }}
          >
            Our Products
          </Typography>
        </Grid>
        <Grid
          item
          xs={12}
          md={3}
          sm={3}
          style={{
            direction: "row",
            justifyContent: "flex-end",
            alignItems: "center",
          }}
        >
          <Dialog />
        </Grid>
      </Grid>
      <Box sx={{ flexGrow: 1, margin: 8 }}>
        <Grid container spacing={3}>
          {getAllProductsFun()?.map((product, index) => (
            <Grid item xs={12} sm={6} md={3} key={index}>
              <Item>
                {" "}
                <Product key={product.id} product={product} />;
              </Item>
            </Grid>
          ))}
        </Grid>
      </Box>
    </>
  );
}

export default Products;

EcommerceServices.js:

import axios from "axios";

// [id]

// get All Products
// export async function getAllProducts() {
//   const res = await axios.get("https://fakestoreapi.com/products");
//   const products = await res.data;
//   console.log("products: ", products);
//   return products;
// }

export async function getAllProducts() {
  const res = await axios
    .get("https://fakestoreapi.com/products")
    .then((res) => {
      const products = res.data;
      console.log("products: ", products);
      return products;
    });

  return res;
}

// get element by ID
export async function getSingleProductRequest(context) {
  const id = context.params.id;
  const req = await axios.get("https://fakestoreapi.com/products/" + id);
  const product = await req.json();
  console.log("product: ", product);
  return product;
}

// get product by ID
export async function getProductsOneByOne() {
  const req = await fetch("https://fakestoreapi.com/products");
  const products = await req.json();
  const paths = products.map((product) => {
    return {
      params: {
        id: product.id.toString(),
      },
    };
  });
  return {
    paths,
    fallback: false,
  };
}

// delete product
export const deleteProduct = async (id) => {
  await axios
    .delete(`https://fakestoreapi.com/products/${id}`)
    .then((res) => {
      res.json();
      console.log("data: ", res.json());
    })
    .then((json) => {
      console.log("json data: ", json);
    })
    .catch((err) => console.log("error: ", err));
};
Hiba Youssef
  • 1,130
  • 1
  • 12
  • 34
  • That function doesn't return anything, so the use of ?. means nothing gets rendered. And if it did return, it would have to be a _promise_ of something. – jonrsharpe Apr 10 '22 at 20:28
  • can u edit my post? – Hiba Youssef Apr 10 '22 at 20:29
  • Does this answer your question? [How to return the response from an asynchronous call](https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – jonrsharpe Apr 10 '22 at 20:29
  • no, this post does't answer my question – Hiba Youssef Apr 10 '22 at 20:30
  • The answers explain the problem and the various ways of dealing with it, including promises, in great detail. I'd suggest you give it more than one minute. – jonrsharpe Apr 10 '22 at 20:32
  • In fact you already have one solution, setting a state variable from the `.then` callback, which you've decided to comment out. – jonrsharpe Apr 10 '22 at 20:36

1 Answers1

1

The problem is that your getAllProductsFun api call is asynchronous. So you'll need to save those values and then display it rather than attempting to call it on render.

In your App.js you can create a state to store the fetched products and call the function on your app mounting like this:

const App = () => {
  const [products, setProducts] = React.useState([]) // defaults to empty array

  ...

  React.useEffect(() => {
    getAllProducts().then(response => setProducts(response))
  }, []) // empty deps array means it will only call once on mount

  return (
    <>
      <Navbar />
      <Products products={products} />
    </>
  );
}

Now you can render the results in Products like this:

function Products({ products }) {
   ...

   return (
     ...
     {products.map(...)}
     ...
   )
}
Barry Michael Doyle
  • 9,333
  • 30
  • 83
  • 143