Hiba Youssef
Hiba Youssef

Reputation: 1390

The data is fetched from the backend, but it is not displayed on the interface

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

Upvotes: 0

Views: 1349

Answers (1)

Barry Michael Doyle
Barry Michael Doyle

Reputation: 10648

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(...)}
     ...
   )
}

Upvotes: 1

Related Questions