React JS PHP MySQLi CRUD Application with React Context API

React JS PHP MySQLi CRUD Application with React Context API

In this tutorial, you will learn how to create A CRUD Application using React JS and PHP MySQLi.

If you want to see a DEMO of this application, then watch the following video –

PHP React JS CRUD Application

First, we will create a CRUD Restful API using PHP And MySQLi. Then we will use this Restful API in our React JS CRUD Application.

PHP CRUD RESTful API

Open your Xampp htdocs folder or Wamp www directory, then here create a new folder and name it php-react.

Below, the list of which files we are going to create inside the php-react folder.

  • db_connection.php
  • add-user.php
  • all-users.php
  • update-user.php
  • delete-user.php

But, before we create these files, first we will set-up our database –

Database name – react_php_crud
Table name – users

Use the below SQL code to create the `users` table and the structure of the `users` table.

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
  `user_email` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
   PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

After set-up our Database, Now we will be creating our files.

db_connection.php

Configure this file according to your database configuration.

<?php
$db_conn = mysqli_connect("localhost","root","","react_php_crud");

add-user.php

<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: access");
header("Access-Control-Allow-Methods: POST");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");

require 'db_connection.php';

// POST DATA
$data = json_decode(file_get_contents("php://input"));

if(isset($data->user_name) 
	&& isset($data->user_email) 
	&& !empty(trim($data->user_name)) 
	&& !empty(trim($data->user_email))
	){
    $username = mysqli_real_escape_string($db_conn, trim($data->user_name));
    $useremail = mysqli_real_escape_string($db_conn, trim($data->user_email));
    if (filter_var($useremail, FILTER_VALIDATE_EMAIL)) {
        $insertUser = mysqli_query($db_conn,"INSERT INTO `users`(`user_name`,`user_email`) VALUES('$username','$useremail')");
        if($insertUser){
            $last_id = mysqli_insert_id($db_conn);
            echo json_encode(["success"=>1,"msg"=>"User Inserted.","id"=>$last_id]);
        }
        else{
            echo json_encode(["success"=>0,"msg"=>"User Not Inserted!"]);
        }
    }
    else{
        echo json_encode(["success"=>0,"msg"=>"Invalid Email Address!"]);
    }
}
else{
    echo json_encode(["success"=>0,"msg"=>"Please fill all the required fields!"]);
}

all-users.php

<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: access");
header("Access-Control-Allow-Methods: GET");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");

require 'db_connection.php';

$allUsers = mysqli_query($db_conn,"SELECT * FROM `users`");
if(mysqli_num_rows($allUsers) > 0){
    $all_users = mysqli_fetch_all($allUsers,MYSQLI_ASSOC);
    echo json_encode(["success"=>1,"users"=>$all_users]);
}
else{
    echo json_encode(["success"=>0]);
}

update-user.php

<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: access");
header("Access-Control-Allow-Methods: POST");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");

require 'db_connection.php';

$data = json_decode(file_get_contents("php://input"));

if(isset($data->id) 
	&& isset($data->user_name) 
	&& isset($data->user_email) 
	&& is_numeric($data->id) 
	&& !empty(trim($data->user_name)) 
	&& !empty(trim($data->user_email))
	){
    $username = mysqli_real_escape_string($db_conn, trim($data->user_name));
    $useremail = mysqli_real_escape_string($db_conn, trim($data->user_email));
    if (filter_var($useremail, FILTER_VALIDATE_EMAIL)) {
        $updateUser = mysqli_query($db_conn,"UPDATE `users` SET `user_name`='$username', `user_email`='$useremail' WHERE `id`='$data->id'");
        if($updateUser){
            echo json_encode(["success"=>1,"msg"=>"User Updated."]);
        }
        else{
            echo json_encode(["success"=>0,"msg"=>"User Not Updated!"]);
        }
    }
    else{
        echo json_encode(["success"=>0,"msg"=>"Invalid Email Address!"]);
    }
}
else{
    echo json_encode(["success"=>0,"msg"=>"Please fill all the required fields!"]);
}

delete-user.php

<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: access");
header("Access-Control-Allow-Methods: POST");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");

require 'db_connection.php';

$data = json_decode(file_get_contents("php://input"));
if(isset($data->id) && is_numeric($data->id)){
    $delID = $data->id;
    $deleteUser = mysqli_query($db_conn,"DELETE FROM `users` WHERE `id`='$delID'");
    if($deleteUser){
        echo json_encode(["success"=>1,"msg"=>"User Deleted"]);
    }
    else{
        echo json_encode(["success"=>0,"msg"=>"User Not Found!"]);
    }
}
else{
    echo json_encode(["success"=>0,"msg"=>"User Not Found!"]);
}

API URLs:

For adding new user – http://localhost/php-react/add-user.php
Fetch all users from Database – http://localhost/php-react/all-users.php
Update User – http://localhost/php-react/update-user.php
Delete User – http://localhost/php-react/delete-user.php


React JS CRUD Application

Before we start to create this React JS CRUD application, I suggest you first, Read this – React JS CRUD Application

First, install the React js, and create a new React CLI Environment called as you wish. Here I name it php-react-crud

After that, open your react project in your favorite editor. To create this we’ll not focus on CSS for that we will use bootstrap.

So, open the public folder and here you can see the index.html file. open this HTML file and copy the below bootstrap CDN link and paste into the head section of the index.html

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">

To make HTTP requests we will use the Axios js, so install the Axios js by running the npm install axios --save command.


Now we will work with the src folder. So first, delete all the files except the serviceWorker.js inside the src folder.

After that, we will create some files and folders inside the src folder.

Structure of the src folder:

Structure of the php-react-crud src folder

First, inside the src folder create a new file called Context.js, and inside the Context.js we will initialize React JS Context.

Context.js

import React from 'react'
export const AppContext = React.createContext();
export const Provider = AppContext.Provider;

After that create a new folder inside the src folder and name it Actions, then inside the Actions folder create a new file called Actions.js

Through the Actions.js file, we will perform all the crud operations and centralize our state.

Actions.js

import React from 'react';
import Axios from 'axios';
class Actions extends React.Component{
    state = {
        users:[]
    }

    // FETCH USERS FROM DATABASE
    fetchUsers = () => {
        Axios.get('http://localhost/php-react/all-users.php')
        .then(({data}) => {
            if(data.success === 1){
                this.setState({
                    users:data.users.reverse()
                });
            }
        })
        .catch(error => {
            console.log(error);
        })
    }

     // ON EDIT MODE
     editMode = (id) => {
        let users = this.state.users.map(user => {
            if(user.id === id){
                user.isEditing = true;
                return user;
            }
            user.isEditing = false;
            return user;
        });

        this.setState({
            users
        });
    }

    //CANCEL EDIT MODE
    cancelEdit = (id) => {
        let users = this.state.users.map(user => {
            if(user.id === id){
                user.isEditing = false;
                return user;
            }
            return user
            
        });
        this.setState({
            users
        });
    }

    // UPDATE USER
    handleUpdate = (id,user_name,user_email) => {
        Axios.post('http://localhost/php-react/update-user.php',
        {
            id:id,
            user_name:user_name,
            user_email:user_email
        })
        .then(({data}) => {
            if(data.success === 1){
                let users = this.state.users.map(user => {
                    if(user.id === id){
                        user.user_name = user_name;
                        user.user_email = user_email;
                        user.isEditing = false;
                        return user;
                    }
                    return user; 
                });
                this.setState({
                    users
                });
            }
            else{
                alert(data.msg);
            }
        })
        .catch(error => {
            console.log(error);
        });
    }


    // DELETE USER
    handleDelete = (id) => {
        let deleteUser = this.state.users.filter(user => {
            return user.id !== id;
        });
        
        Axios.post('http://localhost/php-react/delete-user.php',{
            id:id
        })
        .then(({data}) => {
            if(data.success === 1){
                this.setState({
                    users:deleteUser
                });
            }
            else{
                alert(data.msg);
            }
        })
        .catch(error => {
            console.log(error);
        });
    }

    // INSERT USER
    insertUser = (event,user_name,user_email) => {
        event.preventDefault();
        event.persist();
        Axios.post('http://localhost/php-react/add-user.php',{
            user_name:user_name,
            user_email:user_email
        })
        .then(function ({data}) {
            if(data.success === 1){
                this.setState({
                    users:[
                        {"id":data.id,"user_name":user_name,"user_email":user_email},
                        ...this.state.users
                    ]
                });
                event.target.reset();
            }
            else{
                alert(data.msg);
            }
        }.bind(this))
        .catch(function (error) {
            console.log(error);
        });
    }
}

export default Actions;

After creating the Actions.js, Now inside the src folder, we need to create one more file called components and inside components folder, we will create AddUser.js and GetUsers.js

AddUser.js

import React,{Component} from 'react';
import {AppContext} from '../Context';

class AddUser extends Component {
    static contextType = AppContext;

    insertUser = (event) => {
        this.context.insertUser(event,this.username.value,this.useremail.value);
    }

    render(){
        return (
            <form onSubmit={this.insertUser}>
            <div className="form-row">
                <div className="form-group col-sm-6">
                    <label className="font-weight-bold">Name</label>
                    <input type="text" name="username" ref={(val) => this.username = val} className="form-control" placeholder="Name"/>
                </div>
                <div className="form-group col-sm-6">
                    <label className="font-weight-bold">Email</label>
                    <input type="email" name="useremail" ref={(val) => this.useremail = val} className="form-control" placeholder="Email"/>
                </div>
                <div className="form-group col-sm-12 text-right">
                    <button type="submit" className="btn btn-primary">Add user</button>
                </div>
            </div>
        </form>  
        );
    }
}
export default AddUser;

GetUsers.js

import React, {Component} from 'react';
import {AppContext} from '../Context';
class GetUsers extends Component{
    static contextType = AppContext;

    componentDidMount(){
        this.context.get_users();
    }

    handleUpdate = (id) => {
        this.context.handleUpdate(id,this.name.value,this.email.value);
    }

    render(){
        let allUsers;
        let mainData;
        
        allUsers = this.context.all_users.map(({id,user_name,user_email,isEditing}) => {
            return isEditing === true ? (
                <tr key={id}>
                <td><input className="form-control" type="text" ref={(item) => this.name = item} defaultValue={user_name}/></td>
                <td><input className="form-control" type="email" ref={(item) => this.email = item} defaultValue={user_email}/></td>
                <td>
                    <button className="btn btn-success mr-2" onClick={() => this.handleUpdate(id)}>Save</button>
                    <button onClick={() => this.context.cancelEdit(id)} className="btn btn-light">Cancel</button>
                </td>
            </tr>
            ) : (
                <tr key={id}>
                    <td>{user_name}</td>
                    <td>{user_email}</td>
                    <td>
                        <button className="btn btn-dark mr-2" onClick={() => this.context.editMode(id)}>Edit</button>
                        <button onClick={() => this.context.handleDelete(id)} className="btn btn-danger">Delete</button>
                    </td>
                </tr>
            );
        });

        if(this.context.all_users.length > 0){
            mainData = (
                <table className="table table-striped table-bordered">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Email</th>
                            <th>Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                        {allUsers}
                    </tbody>
                </table>
            );
        }
        else{
            mainData = (
                <div className="alert alert-light" role="alert">
                    <h4 className="alert-heading">No User Found!</h4>
                    <hr/>
                    <p>Please Insert Some Users.</p>
                </div>
            );
        }
        return(
            <>
            {mainData}
            </>
        );
    }

}
export default GetUsers;

Now we need to create two files inside the src folder – App.js and index.js

App.js

import React from 'react';
import {Provider} from './Context';
import AllUsers from './components/GetUsers';
import AddUser from './components/AddUser';
import Actions from './Actions/Actions';

class App extends Actions {
  render(){
    const contextValue = {
        all_users:this.state.users,
        get_users:this.fetchUsers,
        editMode:this.editMode,
        cancelEdit:this.cancelEdit,
        handleUpdate:this.handleUpdate,
        handleDelete:this.handleDelete,
        insertUser:this.insertUser
    }
    return (
      <Provider value={contextValue}>
        <div className="container-fluid bg-light">
              <div className="container p-5">
                  <div className="card shadow-sm">
                      <h1 className="card-header text-center text-uppercase text-muted">React PHP CRUD Application</h1>
                      <div className="card-body">
                          <div className="row">
                              <div className="col-md-4">
                                  <AddUser/>
                              </div>
                              <div className="col-md-8">
                                <AllUsers/>
                              </div>
                          </div>
                      </div>
                  </div>
      
              </div>
              </div>
      </Provider>
    );
  }
}

export default App;

index.js

import React,{StrictMode} from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(<StrictMode><App /></StrictMode>, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

To test your code strat your apache and MySQL server, and then run your react app by running the npm start command.

Leave a Reply

Your email address will not be published. Required fields are marked *