😍React JS PHP MySQLi CRUD Application with React Context API
https://www.w3jar.com/react-js-php-mysqli-crud-application-with-react-context-api/
Dự án đã hoàn thành ở đây
https://github.com/phamngoctuong/crudapplication
Step 1.1 (Use mysqli)
Create Database
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;
db_connection.php
<?php
$db_conn = mysqli_connect("localhost", "root", "", "lva3");
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!"]);
}
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!"]);
}
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!"]);
}
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]);
}
Step 1.2 (Use PDO)
connect.php
<?php
$servername = "localhost";
$username = "root";
$password = "";
try {
$conn = new PDO("mysql:host=$servername;dbname=lva4", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// echo "Connected successfully 1";
} catch (PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
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_once("connect.php");
try {
$data = json_decode(file_get_contents(filename: "php://input"),associative: true);
$user = $data['user_name'];
$mail = $data['user_email'];
$sql = "INSERT INTO users (user_name, user_email) VALUES ('$user', '$mail')";
$conn->setAttribute(attribute: PDO::ATTR_ERRMODE, value: PDO::ERRMODE_EXCEPTION);
$conn->exec(statement: $sql);
$lastInsertId = $conn->lastInsertId();
echo json_encode(value: ['message' => 1, 'lastInsertId' => $lastInsertId]);
} catch (PDOException $e) {
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
all-users.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_once("connect.php");
try {
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare("SELECT * FROM users");
$stmt->execute();
$result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
echo json_encode(value: $stmt->fetchAll());
} catch (PDOException $e) {
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
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_once("connect.php");
try {
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$data = json_decode(json: file_get_contents(filename: "php://input"), associative: true);
$id = $data['id'];
$sql = "DELETE FROM users WHERE id=$id";
$stmt = $conn->prepare($sql);
$stmt->execute();
echo $stmt->rowCount() . " records Delete successfully id=$id";
} catch (PDOException $e) {
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
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_once("connect.php");
try {
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$data = json_decode(json: file_get_contents(filename: "php://input"), associative: true);
$id = $data['id'];
$user = $data['user_name'];
$mail = $data['user_email'];
$sql = "UPDATE users SET user_name='$user',user_email='$mail' WHERE id=$id";
$stmt = $conn->prepare($sql);
$stmt->execute();
echo $stmt->rowCount() . " records UPDATED successfully id=$id";
} catch (PDOException $e) {
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
Step 2.1 (Kiểu cũ)
public\index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="https://getbootstrap.com/docs/5.3/dist/css/bootstrap.min.css">
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
src\App.tsx
import React, { Component } from 'react';
import { Provider } from './Context';
import AllUsers from './components/GetUsers';
import AddUser from './components/AddUser';
import Actions from './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;
src\Actions.tsx
import Axios from 'axios';
import React, { Component } from 'react';
class Actions extends Component<any, any> {
constructor(props:any) {
super(props);
this.state = {
users: []
}
}
fetchUsers = () => {
Axios.get('https://lva3.com/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: any) => {
let users = this.state.users.map((user: any) => {
if (user.id === id) {
user.isEditing = true;
return user;
}
user.isEditing = false;
return user;
});
this.setState({
users
});
}
//CANCEL EDIT MODE
cancelEdit = (id: any) => {
let users = this.state.users.map((user: any) => {
if (user.id === id) {
user.isEditing = false;
return user;
}
return user
});
this.setState({
users
});
}
// UPDATE USER
handleUpdate = (id: any, user_name: any, user_email: any) => {
Axios.post('https://lva3.com/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: any) => {
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: any) => {
let deleteUser = this.state.users.filter((user: any) => {
return user.id !== id;
});
Axios.post('https://lva3.com/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: any, user_name: any, user_email: any) => {
event.preventDefault();
event.persist();
var rethis = this;
Axios.post('https://lva3.com/add-user.php', {
user_name: user_name,
user_email: user_email
})
.then(function ({ data }: any) {
if (data.success === 1) {
rethis.setState({
users: [
{ "id": data.id, "user_name": user_name, "user_email": user_email },
...rethis.state.users
]
});
event.target.reset();
}
else {
alert(data.msg);
}
}.bind(this))
.catch(function (error) {
console.log(error);
});
}
render() {
return (
<div>
</div>
);
}
}
export default Actions;
src\Context.tsx
import React, { createContext } from 'react'
export const AppContext:any = createContext(null);
export const Provider:any = AppContext.Provider;
src\components\AddUser.jsx
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 mt-2">
<button type="submit" className="btn btn-primary">Add user</button>
</div>
</div>
</form>
);
}
}
export default AddUser;
src\components\GetUsers.jsx
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 mx-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;
Chú ý: Sử dụng static contextType = AppContext; thì mới sử dụng được this.content (Đây là cách mới trước kia phức tạp hơn)
static contextType = AppContext;
Step 2.2 (Kiểu class mới)
src\Context.tsx
import React, { createContext } from 'react'
export const AppContext:any = createContext(null);
export const Provider:any = AppContext.Provider;
src\App.tsx
import React, { Component } from 'react';
import AddUserComponent from './components/addUserComponent';
import ListUserComponent from './components/listUserComponent';
import apiCaller from './Actions';
import { Provider } from "./Context";
class App extends Component<any, any> {
constructor(props: any) {
super(props);
this.state = {
users: []
}
}
fetchUsers() {
apiCaller('all-users.php', 'GET', {}).then((res: any) => {
this.setState({
users: res.data
});
})
}
componentDidMount(): void {
this.fetchUsers();
}
insertUser = (event: any, user_name: any, user_email: any) => {
event.preventDefault();
apiCaller('add-user.php', 'POST', { user_name, user_email }).then((res) => {
event.target.reset();
})
}
handleDelete = (id: any) => {
apiCaller('delete-user.php', 'POST', { id });
}
editMode = (id: any) => {
let users = this.state.users.map((user: any) => {
if (user.id === id) {
user.isEditing = true;
return user;
}
user.isEditing = false;
return user;
});
this.setState({
users
});
}
cancelEdit = (id: any) => {
let users = this.state.users.map((user: any) => {
if (user.id === id) {
user.isEditing = false;
return user;
}
return user
});
this.setState({
users
});
}
handleUpdate = (id: any, user_name: any, user_email: any) => {
apiCaller('update-user.php', 'POST', { id, user_name, user_email });
}
render() {
const contextValue = {
users: this.state.users,
insertUser: this.insertUser,
handleDelete: this.handleDelete,
editMode: this.editMode,
cancelEdit: this.cancelEdit,
handleUpdate: this.handleUpdate
}
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">
<AddUserComponent />
<ListUserComponent />
</div>
</div>
</div>
</div>
</div>
</Provider>
);
}
}
export default App;
src\Actions.tsx
import axios from 'axios';
export default function apiCaller(endpoint: (string | number), method: string, body: object) {
return axios({
method: method,
url: `https://lva4.com/${endpoint}`,
data: body
}).catch(error => {
console.log(`https://lva4.com/${endpoint}`);
});
}
src\components\listUserComponent.jsx
import React, { Component } from 'react';
import axios from 'axios';
import { AppContext } from '../Context';
class listUserComponent extends Component {
static contextType = AppContext;
handleUpdate = (id) => {
this.context.handleUpdate(id, this.name.value, this.email.value);
}
render() {
var { users } = this.context;
var allUsers = 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 mx-2" onClick={() => this.handleUpdate(id)}>Save {id}</button>
<button onClick={() => this.context.cancelEdit(id)} className="btn btn-light">Cancel {id}</button>
</td>
</tr>
)
) : (
<tr key={id}>
<td>{user_name}</td>
<td>{user_email}</td>
<td>
<button className="btn btn-dark mx-2" onClick={() => this.context.editMode(id)}>Edit {id}</button>
<button className="btn btn-danger" onClick={() => this.context.handleDelete(id)}>Delete {id}</button>
</td>
</tr>
);
});
return (
<div className="col-md-8">
<table className="table table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{allUsers}
</tbody>
</table>
</div>
);
}
}
export default listUserComponent;
src\components\addUserComponent.jsx
import React, { Component } from 'react';
import { AppContext } from '../Context';
class addUserComponent extends Component {
static contextType = AppContext;
insertUser = (event) => {
event.preventDefault();
this.context.insertUser(event, this.username.value, this.useremail.value);
}
render() {
return (
<div className="col-md-4">
<form onSubmit={this.insertUser}>
<div className="form-row">
<div className="form-group col-sm-6">
<label className="font-weight-bold">Name</label>
<input className="form-control" placeholder="Name" type="text" name="username" ref={(val) => this.username = val} />
</div>
<div className="form-group col-sm-6">
<label className="font-weight-bold">Email</label>
<input className="form-control" placeholder="Email" type="email" name="useremail" ref={(val) => this.useremail = val} />
</div>
<div className="form-group col-sm-12 text-right mt-2">
<button type="submit" className="btn btn-primary">Add user</button>
</div>
</div>
</form>
</div>
);
}
}
export default addUserComponent;
Step 2.3 (Kiểu Function mới)
src\App.tsx
import { useState, useEffect} from "react";
var _ = require('lodash');
function App() {
var [users, setUser] = useState<any>([]);
let nameRef: HTMLInputElement | null;
let emailRef: HTMLInputElement | null;
useEffect(() => {
fetch('https://lva3.com/all-user.php')
.then(response => response.json())
.then(data => {
const newArr = data.map((v: any) => ({ ...v, isActive: false }))
return setUser(newArr);
})
}, []);
const submit = (e: any) => {
e.preventDefault();
var name = nameRef?.value;
var email = emailRef?.value;
fetch('https://lva3.com/add-user.php',
{
// Adding method type
method: "POST",
// Adding body or contents to send
body: JSON.stringify({
user_name: name,
user_email: email
}),
// Adding headers to the request
headers: {
"Content-type": "application/json; charset=UTF-8"
}
}
)// Converting to JSON
.then(response => response.json())
// Displaying results to console
.then(json => console.log(json));
}
const deleteU = (id: number) => {
fetch('https://lva3.com/delete-user.php',
{
// Adding method type
method: "POST",
// Adding body or contents to send
body: JSON.stringify({
id
}),
// Adding headers to the request
headers: {
"Content-type": "application/json; charset=UTF-8"
}
}
)// Converting to JSON
.then(response => response.json())
// Displaying results to console
.then(json => console.log(json));
}
const EditU = (user: any) => {
let index = _.findIndex(users, function (o: any) {
return o.id === user.id;
});
users = users.map((v: any, ind: number) => {
if (ind === index) {
return { ...v, isActive: !users[index].isActive };
}
return (
{ ...v, isActive: false }
)
})
setUser(users);
}
const handleUpdate = async (user: any) => {
var name = nameRef?.value;
var email = emailRef?.value;
await fetch('https://lva3.com/edit-user.php',
{
// Adding method type
method: "POST",
// Adding body or contents to send
body: JSON.stringify({
user_id: user.id,
user_name: name,
user_email: email
}),
// Adding headers to the request
headers: {
"Content-type": "application/json; charset=UTF-8"
}
}
)// Converting to JSON
.then(response => response.json())
// Displaying results to console
.then(json => console.log(json));
}
return (
<div className="w-screen">
<section className="bg-white dark:bg-dark py-20 lg:py-[120px]">
<div className="container mx-auto">
<div className="flex flex-row">
<div className="basis-1/3 pr-3">
<form onSubmit={submit}>
<div className="grid xl:grid-cols-1 xl:gap-6">
<div className="relative z-0 mb-6 w-full group">
<input ref={node => { nameRef = node; }} type="text" className="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer" placeholder="Enter Name" required />
<label className="absolute text-sm text-gray-500 dark:text-gray-400 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:left-0 peer-focus:text-blue-600 peer-focus:dark:text-blue-500 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">First name</label>
</div>
</div>
<div className="relative z-0 mb-6 w-full group">
<input ref={node => { emailRef = node; }} type="email" className="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer" placeholder=" " required />
<label htmlFor="floating_email" className="absolute text-sm text-gray-500 dark:text-gray-400 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:left-0 peer-focus:text-blue-600 peer-focus:dark:text-blue-500 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">Email address</label>
</div>
<button type="submit" className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Submit</button>
</form>
<p className="mt-5">Check out the original floating label form elements on and browse other similar components built with Tailwind CSS.
</p>
</div>
<div className="basis-2/3 border-t border-[#E8E8E8]">
<div className="max-w-full overflow-x-auto">
<table className="w-full table-auto">
<thead>
<tr className="text-center bg-primary">
<th className="w-1/3 min-w-[160px] border-transparent bg-[#F3F6FF] py-4 px-3 text-lg font-medium text-black lg:py-7 lg:px-4">
Name
</th>
<th className="w-1/3 min-w-[160px] py-4 px-3 text-lg font-medium bg-[#F3F6FF] text-black lg:py-7 lg:px-4">
Email
</th>
<th className="w-1/3 min-w-[160px] py-4 px-3 text-lg font-medium bg-[#F3F6FF] text-black lg:py-7 lg:px-4">
Action
</th>
</tr>
</thead>
<tbody>
{
users.map((user: any, index: number) => (
<tr key={index}>
<td className="text-dark border-b border-[#E8E8E8] dark:bg-dark-3 dark:border-dark dark:text-dark-7 py-5 px-2 text-center text-base font-medium">
{!user.isActive ? user.user_name : <input ref={node => { nameRef = node; }} defaultValue={user.user_name} type="text" className="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer" placeholder="Enter Name" required />}
</td>
<td className="text-dark border-b border-[#E8E8E8] dark:border-dark dark:bg-dark-2 dark:text-dark-7 py-5 px-2 text-center text-base font-medium">
{!user.isActive ? user.user_email : <input ref={node => { emailRef = node; }} defaultValue={user.user_email} type="email" className="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer" placeholder=" " required />}
</td>
<td className="text-dark border-b border-[#E8E8E8] dark:bg-dark-3 dark:border-dark dark:text-dark-7 py-5 px-2 text-center text-base font-medium">
{user.isActive ? <button className="px-4 py-2 font-semibold text-sm bg-gray-950 text-white rounded-full shadow-sm" onClick={() => handleUpdate(user)}>Save</button> : ""}
<button onClick={() => EditU(user)} className="px-4 py-2 font-semibold text-sm bg-cyan-500 text-white rounded-full shadow-sm">Edit</button>
<button onClick={() => deleteU(user.id)} className="px-4 py-2 font-semibold text-sm bg-pink-500 text-white rounded-full shadow-sm">Delete</button>
</td>
</tr>
))
}
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>
</div>
);
}
export default App;
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.
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.Prevphp if, if else and if elseif else statementNextjquery ajax image and file upload in php and mysqli with progressbar
RELATED POSTS
Last updated
Was this helpful?