Build a Full Stack Book Store App Using React, Node, MongoDB

Creating a full stack application is an excellent way to enhance your web development skills. We will walk through the process of building a full stack book store app using React for the front end, Node.js for the back end, and MongoDB for the database. This project will give you hands-on experience with the MERN stack (MongoDB, Express, React, Node.js) and help you understand how to manage both the client and server sides of a web application.

Before we dive into the code, make sure you have the following installed on your machine:

  • Node.js: This will allow you to run JavaScript on the server side.
  • MongoDB: A NoSQL database to store your book data.
  • npm: Node package manager, which comes with Node.js.
  • Basic knowledge of JavaScript and familiarity with React and Node.js concepts.

Project Structure

We’ll create a project structure that separates the front end and back end:

book-store-app/
├── client/          # React front end
└── server/          # Node.js back end

Setting Up the Server

First, let’s set up the back end using Node.js and Express.

Initialize the Server

Navigate to the server directory and initialize a new Node.js project:

mkdir server
cd server
npm init -y

Install Dependencies

Install the necessary packages:

npm install express mongoose cors dotenv
  • express: A web framework for Node.js.
  • mongoose: An ODM (Object Data Modeling) library for MongoDB.
  • cors: A middleware to enable CORS (Cross-Origin Resource Sharing).
  • dotenv: A module to load environment variables from a .env file.

Create the Server File

Create a file named server.js in the server directory:

const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
require('dotenv').config();

const app = express();
const PORT = process.env.PORT || 5000;

// Middleware
app.use(cors());
app.use(express.json());

// MongoDB connection
mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true })
    .then(() => console.log('MongoDB connected'))
    .catch(err => console.error(err));

// Start the server
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

Create the Book Model

Create a models directory and a Book.js file inside it:

const mongoose = require('mongoose');

const bookSchema = new mongoose.Schema({
    title: { type: String, required: true },
    author: { type: String, required: true },
    description: { type: String, required: true },
    price: { type: Number, required: true },
    imageUrl: { type: String, required: true }
});

module.exports = mongoose.model('Book', bookSchema);

Create Routes for Books

Create a routes directory and a books.js file inside it:

const express = require('express');
const router = express.Router();
const Book = require('../models/Book');

// Get all books
router.get('/', async (req, res) => {
    try {
        const books = await Book.find();
        res.json(books);
    } catch (err) {
        res.status(500).json({ message: err.message });
    }
});

// Add a new book
router.post('/', async (req, res) => {
    const book = new Book(req.body);
    try {
        const savedBook = await book.save();
        res.status(201).json(savedBook);
    } catch (err) {
        res.status(400).json({ message: err.message });
    }
});

module.exports = router;

Connect Routes to the Server

In server.js, import and use the routes:

const bookRoutes = require('./routes/books');
app.use('/api/books', bookRoutes);

Setting Up the Client

Now, let’s set up the front end using React.

Create the React App

Navigate back to the root directory and create a React app:

npx create-react-app client
cd client

Install Axios

Install Axios for making HTTP requests:

npm install axios

Create Components

Create a components directory and add the following components:

  • BookList.js: To display the list of books.
  • AddBook.js: To add a new book.

BookList.js

import React, { useEffect, useState } from 'react';
import axios from 'axios';

const BookList = () => {
    const [books, setBooks] = useState([]);

    useEffect(() => {
        const fetchBooks = async () => {
            const response = await axios.get('http://localhost:5000/api/books');
            setBooks(response.data);
        };
        fetchBooks();
    }, []);

    return (
        <div>
            <h2>Book List</h2>
            <ul>
                {books.map(book => (
                    <li key={book._id}>{book.title} by {book.author}</li>
                ))}
            </ul>
        </div>
    );
};

export default BookList;

AddBook.js

import React, { useState } from 'react';
import axios from 'axios';

const AddBook = () => {
    const [book, setBook] = useState({ title: '', author: '', description: '', price: '', imageUrl: '' });

    const handleChange = (e) => {
        setBook({ ...book, [e.target.name]: e.target.value });
    };

    const handleSubmit = async (e) => {
        e.preventDefault();
        await axios.post('http://localhost:5000/api/books', book);
        setBook({ title: '', author: '', description: '', price: '', imageUrl: '' });
    };

    return (
        <form onSubmit={handleSubmit}>
            <input name="title" value={book.title} onChange={handleChange} placeholder="Title" required />
            <input name="author" value={book.author} onChange={handleChange} placeholder="Author" required />
            <textarea name="description" value={book.description} onChange={handleChange} placeholder="Description" required />
            <input name="price" type="number" value={book.price} onChange={handleChange} placeholder="Price" required />
            <input name="imageUrl" value={book.imageUrl} onChange={handleChange} placeholder="Image URL" required />
            <button type="submit">Add Book</button>
        </form>
    );
};

export default AddBook;

Update App.js

In src/App.js, import and use the components:

import React from 'react';
import BookList from './components/BookList';
import AddBook from './components/AddBook';

const App = () => {
    return (
        <div>
            <h1>Book Store</h1>
            <AddBook />
            <BookList />
        </div>
    );
};

export default App;

Running the Application

Start the Server

In the server directory, run:

node server.js

Start the Client

In the client directory, run:

npm start

Conclusion

Congratulations! You have successfully built a full stack book store application using React, Node.js, and MongoDB. This project not only helps you understand the MERN stack but also gives you a practical application that you can expand upon. You can add features like user authentication, book reviews, and more to enhance your app further. Happy coding!

Related blog posts