CRUD tutorial using Node JS, React JS, Express, and MySQL

In accordance with the title of my tutorial, I will try to discuss about creating a CRUD system (Create, Read, Update, Delete) using Node JS, React JS, Express, and MySQL, here I use several tools such as Node JS version v16.13.0, React JS, NPM version 8.1.0, Express version 4.17.3 and MySQL2 version 2.3.3 as databases. Here I assume you have installed Node JS if not you can follow the tutorial here. I use the Visual Studio Code text editor to write the code, if not, please download it…

Ok, let’s start, let’s start the tutorial :

List of contents :

  1. Creating project folders and package.json files
  2. Installations of Express, MySQL, Sequelize, Cors and nodemon
  3. Creating databases and tables in MySQL
  4. File structure
  5. Creating database connections, Controllers, Routes and Models
  6. Creating frontend view
  7. Creating component
  8. Testing code
  9. Closing

1. CREATING PROJECT FOLDER AND PACKAGE.JSON FILE

First of all we will create a folder for our project, it can be in D or C or another directory, here I created it in the D directory, the folder I named “crud_react_js”, you can give another name but I suggest using the same name to make it easier to follow then in the crud_react_js folder create a new folder with the name “backend” after that open a command prompt by typing CMD then move to our project directory with the command “D:” then enter the rcud_react_js directory with the command “cd rcud_react_js” then type the command “npm init -y” to create a “package.json” file as shown below

2. INSTALLATIONS OF EXPRESS, MySQL2, SEQUELIZE, CORS AND NODEMON

Express.js is a JavaScript-based framework that is intended for Node.js where the architecture uses MVC (Model View Controller) with data flows that are processed in the Model, then connected through the Controller, and displayed as information through the View. Express.js is open source or free which was born around 2010.

after we create the package.json file, then we will install “express, mysql2, sequelize cors” by typing the command “npm install express mysql2 sequelize cors” as shown below

Congratulations, we have successfully installed Express, MySQL2, Sequelize and Cors, then we will install Nodemon by typing the command “D:\crud_react_js>npm install –global nodemon”, if successful it will look like the image below

Congratulations, we have successfully installed nodemon, next we will make changes to the “package.json” file, this file is located in “D:\crud_react_js\backend” according to the folder where you work.

open the “package.json” file in an editor like notepad or Visual studio code or something else then add the code “type”: “module”, This is so we can use ES6 Module Syntax to export and import modules. it looks like the picture below

3. CREATE DATABASE AND TABLES IN MYSQL

It’s time for us to create a database and table for storing our data later, here I assume you have installed XAMPP, WAMP, MAMP, or other similar software, if not you can read the tutorial on installing XAMPP here

first we will create a database with the name “db_crud” with a query command like this “CREATE DATABASE mern_db;” like the picture below

then click GO at the bottom right so that the query that we make is processed immediately. after the database has been successfully created, we will create a table, we will create a “products” table. To create a “products” table, you can do this by running the following SQL command:

CREATE TABLE products(
product id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(200),
DOUBLE PRICE,
date_create DATE,
date_update DATE
)ENGINE=INNODB;

like the picture below:

4. FILE STRUCTURE

Here we will apply the MVC pattern (Model, View, Controllers).

We will create “config”, “controllers”, “models”, and “routes” folders in the “backend” folder.

We also create a “database.js” file in the “config” folder, then create a “Products.js” file in the “controllers” folder, create a “productModel.js” file in the “models” folder, create an “index.js” file in the the “routes” folder, and finally we will create an “index.js” file in the “backend” folder.

Look at the following image for more details:

5. CREATE DATABASE CONNECTIONS, CONTROLLERS, ROUTES AND MODELS

FIRST we will create a file to connect to the database, earlier we have created a database.js file in the config folder, open the database.js file and add the following code:

import { Sequelize } from “sequelize”;
const db = new Sequelize(‘db_crud’, ‘root’, “, {
hosts: “localhost”,
dialect: “mysql”
});
export default db;

then save.

SECOND we will create a controller, earlier we created the Products.js file which is in the Controllers folder, open Products.js and add the following code:

import Product from "../models/productModel.js";

export const getAllProducts = async (req, res) => {
    try {
        const products = await Product.findAll();
        res.json(products);
    } catch (error) {
        res.json({ message: error.message });
    }  
}

export const getProductById = async (req, res) => {
    try {
        const product = await Product.findAll({
            where: {
                id: req.params.id
            }
        });
        res.json(product[0]);
    } catch (error) {
        res.json({ message: error.message });
    }  
}

export const createProduct = async (req, res) => {
    try {
        await Product.create(req.body);
        res.json({
            "message": "Product Created"
        });
    } catch (error) {
        res.json({ message: error.message });
    }  
}

export const updateProduct = async (req, res) => {
    try {
        await Product.update(req.body, {
            where: {
                id: req.params.id
            }
        });
        res.json({
            "message": "Product Updated"
        });
    } catch (error) {
        res.json({ message: error.message });
    }  
}

export const deleteProduct = async (req, res) => {
    try {
        await Product.destroy({
            where: {
                id: req.params.id
            }
        });
        res.json({
            "message": "Product Deleted"
        });
    } catch (error) {
        res.json({ message: error.message });
    }  
}

THIRD We will create Routes, earlier we have created an index.js file in the routes folder, open index.js and write the following code:

import express from "express";

import { 
    getAllProducts,
    createProduct,
    getProductById,
    updateProduct,
    deleteProduct
} from "../controllers/Products.js";

const router = express.Router();

router.get('/', getAllProducts);
router.get('/:id', getProductById);
router.post('/', createProduct);
router.patch('/:id', updateProduct);
router.delete('/:id', deleteProduct);

export default router;

FOURTH We will create Models, earlier we have created the productModel.js file which is in the models folder, open ProdukModel.js and add the following code

import { Sequelize } from "sequelize";
import db from "../config/database.js";

const { DataTypes } = Sequelize;

const Product = db.define('products',{
    title:{
        type: DataTypes.STRING
    },
    price:{
        type: DataTypes.DOUBLE
    }
},{
    freezeTableName: true
});

export default Product;

NEXT we will add code to the index.js file in the backend folder as shown below (not index.js which is in the routers folder)

then add the following code:

import express from "express";
import db from "./config/database.js";
import productRoutes from "./routes/index.js";
import cors from "cors";

const app = express();

try {
    await db.authenticate();
    console.log('Database connected...');
} catch (error) {
    console.error('Connection error:', error);
}

app.use(cors());
app.use(express.json());
app.use('/products', productRoutes);

app.listen(5000, () => console.log('Server running at port 5000'));

to make sure the application is running correctly we check with the command “nodemon index” but before running it you must activate “MySQL” and the “Localhost” server as shown below

then just in the visual studio code we open a new terminal then type “nodemon index” and if it works it will look like the image below

6. CREATING FRONTEND VIEW

For the front end, we will use React JS.

Open a new terminal in Visual Studio Code and type the following command in the terminal: “npx create-react-app frontend“

like the picture below

Here we will use bulma css, Bulma is a responsive css framework.

After successfully creating a frontend folder and installing reactjs, please enter the frontend folder with the command “cd frontend” and install bulma css by typing the command “npm install react-router-dom axios bulma” as shown below

after successful we will run our project by typing “npm start” as shown below

if it doesn’t appear you can open a browser and type “http://localhost:3000” but you have to activate the localhost server and MySQL first.

7. CREATING COMPONENTS

we will create a new folder in “frontend/src” with the name “components” after that we will create 3 new files with the names “ProductList.js”, “AddProduct.js”, and “EditProduct.js” as shown below

after that we will fill in the coding of the 3 files one by one, we start with “ProductList.js” open and type the following code and save

import React from "react";
import { useState, useEffect } from 'react';
import axios from "axios";
import { Link } from "react-router-dom";
 
const ProductList = () => {
    const [products, setProduct] = useState([]);
 
    useEffect(() => {
        getProducts();
    }, []);
 
    const getProducts = async () => {
        const response = await axios.get('http://localhost:5000/products');
        setProduct(response.data);
        
        
    }
 
    const deleteProduct = async (id) => {
        await axios.delete(`http://localhost:5000/products/${id}`);
        getProducts();
    }
 
    return (
        <div>
            <Link to="/add" className="button is-primary mt-2">Add New</Link>
            <table className="table is-striped is-fullwidth">
                <thead>
                    <tr>
                        <th>No</th>
                        <th>Title</th>
                        <th>Price</th>
                        <th>Actions</th>
                    </tr>
                </thead>
                <tbody>
                    { products.map((product, index) => (
                        <tr key={ product.id }>
                            <td>{ index + 1 }</td>
                            <td>{ product.title }</td>
                            <td>{ product.price }</td>
                            <td>
                                <Link to={`/edit/${product.id}`} className="button is-small is-info">Edit</Link>
                                <button onClick={ () => deleteProduct(product.id) } className="button is-small is-danger">Delete</button>
                            </td>
                        </tr>
                    )) }
                     
                </tbody>
            </table>
        </div>
    )
}
 
export default ProductList

after that edit “AddProduct.js” open it and type the following code and save it

import { useState } from 'react'
import axios from "axios";
import { useNavigate } from 'react-router-dom';
 
const AddProduct = () => {
    const [title, setTitle] = useState('');
    const [price, setPrice] = useState('');
    const navigate = useNavigate();
 
    const saveProduct = async (e) => {
        e.preventDefault();
        await axios.post('http://localhost:5000/products',{
            title: title,
            price: price
        });
        //redirect setelah save;
        navigate('/');
    }
 
    return (
        <div>
            <form onSubmit={ saveProduct }>
                <div className="field">
                    <label className="label">Title</label>
                    <input 
                        className="input"
                        type="text"
                        placeholder="Title"
                        value={ title }
                        onChange={ (e) => setTitle(e.target.value) }
                    />
                </div>
 
                <div className="field">
                    <label className="label">Price</label>
                    <input 
                        className="input"
                        type="text"
                        placeholder="Price"
                        value={ price }
                        onChange={ (e) => setPrice(e.target.value) }
                    />
                </div>
 
                <div className="field">
                    <button className="button is-primary">Save</button>
                </div>
            </form>
        </div>
    )
}
 
export default AddProduct

after that edit “EditProduct.js” open it and type the following code and save it

import { useState, useEffect } from 'react'
import axios from "axios";
import { useNavigate, useParams } from 'react-router-dom';
 
const EditProduct = () => {
    const [title, setTitle] = useState('');
    const [price, setPrice] = useState('');
    const navigate = useNavigate();
    const { id } = useParams();
 
    const updateProduct = async (e) => {
        e.preventDefault();
        await axios.patch(`http://localhost:5000/products/${id}`,{
            title: title,
            price: price
        });
        //redirect setelah save;
        navigate('/');
    }
 
    useEffect(() => {
        getProductById();
    }, []);
 
    const getProductById = async () => {
        const response = await axios.get(`http://localhost:5000/products/${id}`);
        setTitle(response.data.title);
        setPrice(response.data.price);
    }
 
    return (
        <div>
            <form onSubmit={ updateProduct }>
                <div className="field">
                    <label className="label">Title</label>
                    <input 
                        className="input"
                        type="text"
                        placeholder="Title"
                        value={ title }
                        onChange={ (e) => setTitle(e.target.value) }
                    />
                </div>
 
                <div className="field">
                    <label className="label">Price</label>
                    <input 
                        className="input"
                        type="text"
                        placeholder="Price"
                        value={ price }
                        onChange={ (e) => setPrice(e.target.value) }
                    />
                </div>
 
                <div className="field">
                    <button className="button is-primary">Update</button>
                </div>
            </form>
        </div>
    )
}
 
export default EditProduct

After we fill in the coding to the 3 files “ProductList.js”, “AddProduct.js”, and “EditProduct.js” we will edit the App.js file and type the following code and save

import { BrowserRouter as Router, Route, Routes, Link } from "react-router-dom";
import ProductList from "./components/ProductList";
import AddProduct from "./components/AddProduct";
import EditProduct from "./components/EditProduct";

 
function App() {
  return (
    <div className="container">
      <div className="columns">
        <div className="column is-half is-offset-one-quarter">
        <Router>
          <Routes>
            <Route exact path="/" element={<ProductList />} />
            <Route path="/add" element={<AddProduct />} />
            <Route path="/edit/:id" element={<EditProduct />} />
          </Routes>
        </Router>
        </div>
      </div>
    </div>
  );
}


export default App;

7. TESTING

after we make everything, it’s time now we will test the application that we have made.

First we will activate nodemon by:

  • in Visual Studio Code click Terminal > New Terminal
  • go to backend directory
  • type nodemon index, if successful, the image below will appear

Second, we will enable npm by:

  • in Visual Studio Code click Terminal > Split Terminal (a new terminal will appear next to the terminal we created earlier)
  • Go to the frontend directory
  • Type npm start, if successful it will appear as shown below

Open the browser then type “http://localhost:3000” if everything goes well it will appear like the image below

it’s time to test the edit button if everything goes well an image will appear like the image below

please edit the title and price then click the update button to save the data, for the delete process you can directly press the delete button, if the selected data is deleted it means the delete function is correct

8. CLOSING

So I made this tutorial, hopefully it can be useful for beginner programmers who are just learning React js like me, thank you.