Project Goals
In this third stage of the MERN project, you will:
- Create a single-page app in ReactJS to support multiple routes and install the required npm packages.
- Add pages and components to the ReactJS app.
- Display MongoDB product data, via an Express backend routes, in your ReactJS frontend app home page.
Installing the frontend packages
In this stage of your MERN full-stack project, you will set up a single-page application (SPA) on the frontend.
Begin by installing the following packages in your /frontend folder:
npm i react-router-dom axios @mui/material @emotion/react @emotion/styled
Updating your main.jsx
file
Here are the steps to add routes for the 'pages' of your SPA.
-
In your frontend/src subfolder, open the
main.jsx file and delete the import
index.css statement.
-
Add this new import statement:
import { HashRouter as Router, Routes, Route } from "react-router-dom";
-
Inside the <React.StrictMode> tag pair, update the
<App /> component with the following code:
App.jsx will now act as a layout component that wraps around all the ‘pages’ in your frontend ReactJS app.<Router> <Routes> {/* App component wraps around all the 'pages'. */} <Route path="*" element={<App />} /> </Routes> </Router>
Creating your Home page
Follow these steps to create a component that will be the home page of your frontend:
- Inside the frontend/src sub-folder, create a new folder named /pages.
- Inside the /pages folder, create a new text file named HomePage.jsx. This file will serve as your home page.
-
Add the following code to this file:
import React from "react"; const HomePage = () => { return ( <> <h1>My HomePage</h1> </> ); }; export default HomePage;
-
Replace all the content of your frontend/src/App.jsx file
with the following:
// Import Route and Routes from the React router library import { Route, Routes } from "react-router-dom"; // Import the HomePage import HomePage from './pages/HomePage'; function App() { return ( <Routes> {/* Use Home component for the root path */} <Route index element={<HomePage />} /> </Routes> ); } export default App;
If you run the frontend app now in your browser, it should look similar to that below.
![screenshot](assets/img/project-spa/output-frontend.png)
Updating your Home page to display data
Follow these steps to display data from MongoDB, through a route in your Express backend app, in your Home page:
-
Update your HomePage.jsx file as follows:
import React, { useEffect, useState } from "react"; import axios from "axios"; const HomePage = () => { const [productList, setProductList] = useState([]); const getProduct = async () => { try { const response = await axios.get("http://localhost:5000/read"); setProductList(response.data); console.log(response.data); } catch (e) { console.log(e); } }; useEffect(() => { getProduct(); }, []); return ( <> <h1>My HomePage</h1> {/* Map over the productList array to display each product */} {productList.map((product, index) => ( <div key={index}> <h2>{product.name}</h2> <p>{product.description}</p> </div> ))} </> ); }; export default HomePage;
If your Express app is running, your frontend app should now display
in your web browser a list of product titles from the MongoDB
database.
Adding a product card component
Follow these steps:
- In your frontend/src folder, create a new sub-folder named /components.
- Inside this /components sub-folder, create a new text file named ProductCard.jsx.
-
Paste the following code into this file:
import React, { useState } from "react"; import Typography from "@mui/material/Typography"; import Card from "@mui/material/Card"; import CardHeader from "@mui/material/CardHeader"; import CardMedia from "@mui/material/CardMedia"; import CardContent from "@mui/material/CardContent"; import Rating from "@mui/material/Rating"; import Stack from "@mui/material/Stack"; const ProductCard = (props) => { // Initialize product state variable with the product prop const [product, setProduct] = useState(props.product); return ( <> <Card sx={{ width: 345, height: 550, display: "flex", justifyContent: "space-between", flexDirection: "column", }} > <CardHeader title={product.title} /> <CardMedia component="img" height="194" image={product.images} alt="Product image" /> <CardContent> <Stack direction="column" spacing={1}> <Typography variant="body2" color="text.secondary"> {product.description} </Typography> <Stack direction="row" spacing={1}> <Rating name="half-rating-read" defaultValue={product.rating} precision={0.5} readOnly /> <Typography variant="body1" color="text.primary"> {product.rating} </Typography> </Stack> <Stack direction="column"> <Typography variant="body1" color="text.primary"> ${product.price} </Typography> <Typography variant="body1" color="text.primary"> Price discount: {product.discountPercentage}% </Typography> </Stack> </Stack> </CardContent> </Card> </> ); }; export default ProductCard;
-
Update your HomePage.jsx page to use this component.
return ( <> {/* Render a heading with the text "My HomePage" */} <h1>My HomePage</h1> {/* Check if productList is not empty */} {productList.length !== 0 && // If productList is not empty, map over it and render a ProductCard component for each product productList.map((product) => ( // Render a ProductCard component with a unique key and the product as a prop <ProductCard key={product._id} product={product} getProduct={() => getProduct()} /> ))} </> // End of the component's return statement );
In your web browser, you should see a single-column list of product
details in card format.
Project checklist and next step
Before continuing:
![icon](../express-mongodb/assets/img/warning-sign.png)
CHECK that your ReactJS home page can list products using the frontend getProduct() function and the backend http://localhost:5000/read route.
In the next step you will add frontend components and pages to handle CRUD operations with the database.