This article will explain how to perform CRUD (Create, Read, Update and Delete) operations in React JS. We will see step-by-step instructions about CRUD operations in React Js.
Please refer to my previous article,
Before we start, Let's understand the objective of this demonstration which tells what exactly will be covered in this article.
- Create React App
- Adding Bootstrap
- Install Routing
- Adding Components/Pages
- API endpoints
- Navigating menus for routing
- Adding component codes
- Photo Upload
- Filtering & Sorting
So, Let's get started.
Create React App
Open Command Prompt -> Navigate to path where you want to create react app project using below command.
npx create-react-app react-crud
Once react app is created we can check in the folder path.
Now, open react app in VS Code.
Now, open the terminal and run the project.
npm start
Adding Bootstrap
Now go to https://getbootstrap.com/ and copy the bootstrap.min.css and bootstrap.bundle.min.js links.
Open index.html page and past .css link in head section and .js after body section.
Install Routing
Open terminal
npm install react-router-dom
Adding Components/Pages
Now, add components/Pages in react app.
API endpoints
Now, open the Variables.js file and add API end-points
export const variables = {
API_URL: "http://localhost:50306/api/",
PHOTO_URL:"http://localhost:50306/Photos/"
}
Note: Photo_URL is for photos to upload.
Navigating menus for routing
Now, open the App.js file and add routing.
import logo from './logo.svg';
import './App.css';
import { Home } from './Home';
import { Department } from './Department';
import { Employee } from './Employee';
import { BrowserRouter, Route, Switch, NavLink } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<div className="App container">
<h3 className="d-flex justify-content-center m-3">
My React App
</h3>
<nav className="navbar navbar-expand-sm bg-light navbar-dark">
<ul className="navbar-nav">
<li className="nav-item m-1">
<NavLink className="btn btn-light btn-outline-primary" to="/home">
Home
</NavLink>
</li>
<li className="nav-item m-1">
<NavLink className="btn btn-light btn-outline-primary" to="/department">
Department
</NavLink>
</li>
<li className="nav-item m-1">
<NavLink className="btn btn-light btn-outline-primary" to="/employee">
Employee
</NavLink>
</li>
</ul>
</nav>
<switch>
<Route path='/home' component={Home}></Route>
<Route path='/department' component={Department}></Route>
<Route path='/employee' component={Employee}></Route>
</switch>
</div>
</BrowserRouter>
);
}
export default App;
Adding component codes & Filtering & Sorting
Now, Open the Department.js file and add code.
import React, { Component } from 'react';
import { variables } from './Variables.js';
export class Department extends Component {
constructor(props) {
super(props);
this.state = {
departments: [],
modalTitle: "",
DepartmentName: "",
DepartmentId: 0,
DepartmentIdFilter: "",
DepartmentNameFilter: "",
departmentsWithoutFilter: []
}
}
FilterFn() {
var DepartmentIdFilter = this.state.DepartmentIdFilter;
var DepartmentNameFilter = this.state.DepartmentNameFilter;
var filteredData = this.state.departmentsWithoutFilter.filter(
function (el) {
return el.DepartmentId.toString().toLowerCase().includes(
DepartmentIdFilter.toString().trim().toLowerCase()
) &&
el.DepartmentName.toString().toLowerCase().includes(
DepartmentNameFilter.toString().trim().toLowerCase()
)
}
);
this.setState({ departments: filteredData });
}
sortResult(prop, asc) {
var sortedData = this.state.departmentsWithoutFilter.sort(function (a, b) {
if (asc) {
return (a[prop] > b[prop]) ? 1 : ((a[prop] < b[prop]) ? -1 : 0);
}
else {
return (b[prop] > a[prop]) ? 1 : ((b[prop] < a[prop]) ? -1 : 0);
}
});
this.setState({ departments: sortedData });
}
changeDepartmentIdFilter = (e) => {
this.state.DepartmentIdFilter = e.target.value;
this.FilterFn();
}
changeDepartmentNameFilter = (e) => {
this.state.DepartmentNameFilter = e.target.value;
this.FilterFn();
}
refreshList() {
fetch(variables.API_URL + 'department/getDepartment')
.then(response => response.json())
.then(data => {
this.setState({ departments: data, departmentsWithoutFilter: data });
});
}
componentDidMount() {
this.refreshList();
}
changeDepartmentName = (e) => {
this.setState({ DepartmentName: e.target.value });
}
addClick() {
this.setState({
modalTitle: "Add Department",
DepartmentId: 0,
DepartmentName: ""
});
}
editClick(dep) {
this.setState({
modalTitle: "Edit Department",
DepartmentId: dep.DepartmentId,
DepartmentName: dep.DepartmentName
});
}
createClick() {
fetch(variables.API_URL + 'department/adddepartment', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
DepartmentName: this.state.DepartmentName
})
})
.then(res => res.json())
.then((result) => {
alert(result);
this.refreshList();
}, (error) => {
alert('Failed');
})
}
updateClick() {
fetch(variables.API_URL + 'department/updatedepartment', {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
DepartmentId: this.state.DepartmentId,
DepartmentName: this.state.DepartmentName
})
})
.then(res => res.json())
.then((result) => {
alert(result);
this.refreshList();
}, (error) => {
alert('Failed');
})
}
deleteClick(id) {
if (window.confirm('Are you sure?')) {
fetch(variables.API_URL + 'department/deletedepartment/' + id, {
method: 'DELETE',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then((result) => {
alert(result);
this.refreshList();
}, (error) => {
alert('Failed');
})
}
}
render() {
const {
departments,
modalTitle,
DepartmentId,
DepartmentName
} = this.state;
return (
<div>
<button type="button"
className="btn btn-primary m-2 float-end"
data-bs-toggle="modal"
data-bs-target="#exampleModal"
onClick={() => this.addClick()}>
Add Department
</button>
<table className="table table-striped">
<thead>
<tr>
<th>
<div className="d-flex flex-row">
<input className="form-control m-2"
onChange={this.changeDepartmentIdFilter}
placeholder="Filter" />
<button type="button" className="btn btn-light"
onClick={() => this.sortResult('DepartmentId', true)}>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-arrow-down-square-fill" viewBox="0 0 16 16">
<path d="M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5a.5.5 0 0 1 1 0z" />
</svg>
</button>
<button type="button" className="btn btn-light"
onClick={() => this.sortResult('DepartmentId', false)}>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-arrow-up-square-fill" viewBox="0 0 16 16">
<path d="M2 16a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2zm6.5-4.5V5.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 5.707V11.5a.5.5 0 0 0 1 0z" />
</svg>
</button>
</div>
Department Id
</th>
<th>
<div className="d-flex flex-row">
<input className="form-control m-2"
onChange={this.changeDepartmentNameFilter}
placeholder="Filter" />
<button type="button" className="btn btn-light"
onClick={() => this.sortResult('DepartmentName', true)}>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-arrow-down-square-fill" viewBox="0 0 16 16">
<path d="M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5a.5.5 0 0 1 1 0z" />
</svg>
</button>
<button type="button" className="btn btn-light"
onClick={() => this.sortResult('DepartmentName', false)}>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-arrow-up-square-fill" viewBox="0 0 16 16">
<path d="M2 16a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2zm6.5-4.5V5.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 5.707V11.5a.5.5 0 0 0 1 0z" />
</svg>
</button>
</div>
Department Name
</th>
<th>
Options
</th>
</tr>
</thead>
<tbody>
{departments.map(dep =>
<tr key={dep.DepartmentId}>
<td>{dep.DepartmentId}</td>
<td>{dep.DepartmentName}</td>
<td>
<button type="button"
className="btn btn-light mr-1"
data-bs-toggle="modal"
data-bs-target="#exampleModal"
onClick={() => this.editClick(dep)}>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-pencil-square" viewBox="0 0 16 16">
<path d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z" />
<path fillRule="evenodd" d="M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0 0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-1H2.5A1.5 1.5 0 0 0 1 2.5v11z" />
</svg>
</button>
<button type="button"
className="btn btn-light mr-1"
onClick={() => this.deleteClick(dep.DepartmentId)}>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-trash-fill" viewBox="0 0 16 16">
<path d="M2.5 1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1H3v9a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4h.5a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H10a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1H2.5zm3 4a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5zM8 5a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7A.5.5 0 0 1 8 5zm3 .5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 1 0z" />
</svg>
</button>
</td>
</tr>
)}
</tbody>
</table>
<div className="modal fade" id="exampleModal" tabIndex="-1" aria-hidden="true">
<div className="modal-dialog modal-lg modal-dialog-centered">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title">{modalTitle}</h5>
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"
></button>
</div>
<div className="modal-body">
<div className="input-group mb-3">
<span className="input-group-text">Department Name</span>
<input type="text" className="form-control"
value={DepartmentName}
onChange={this.changeDepartmentName} />
</div>
{DepartmentId === 0 ?
<button type="button"
className="btn btn-primary float-start"
onClick={() => this.createClick()}
>Create</button>
: null}
{DepartmentId !== 0 ?
<button type="button"
className="btn btn-primary float-start"
onClick={() => this.updateClick()}
>Update</button>
: null}
</div>
</div>
</div>
</div>
</div>
)
}
}
Now, open the Employee.js file and add code.
Note
I have also added the Photo upload code.
import React, { Component } from 'react';
import { variables } from './Variables.js';
export class Employee extends Component {
constructor(props) {
super(props);
this.state = {
departments: [],
employees: [],
modalTitle: "",
EmployeeId: 0,
EmployeeName: "",
Department: "",
DateOfJoining: "",
PhotoFileName: "anonymous.png",
PhotoPath: variables.PHOTO_URL
}
}
refreshList() {
fetch(variables.API_URL + 'employee/GetEmployee')
.then(response => response.json())
.then(data => {
this.setState({ employees: data });
});
fetch(variables.API_URL + 'department/getDepartment')
.then(response => response.json())
.then(data => {
this.setState({ departments: data });
});
}
componentDidMount() {
this.refreshList();
}
changeEmployeeName = (e) => {
this.setState({ EmployeeName: e.target.value });
}
changeDepartment = (e) => {
this.setState({ Department: e.target.value });
}
changeDateOfJoining = (e) => {
this.setState({ DateOfJoining: e.target.value });
}
addClick() {
this.setState({
modalTitle: "Add Employee",
EmployeeId: 0,
EmployeeName: "",
Department: "",
DateOfJoining: "",
PhotoFileName: "anonymous.png"
});
}
editClick(emp) {
debugger;
this.setState({
modalTitle: "Edit Employee",
EmployeeId: emp.EmployeeId,
EmployeeName: emp.EmployeeName,
Department: emp.Department,
DateOfJoining: emp.DateOfJoining,
PhotoFileName: emp.PhotoFileName
});
}
createClick() {
fetch(variables.API_URL + 'employee/addemployee', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
EmployeeName: this.state.EmployeeName,
Department: this.state.Department,
DateOfJoining: this.state.DateOfJoining,
PhotoFileName: this.state.PhotoFileName
})
})
.then(res => res.json())
.then((result) => {
alert(result);
this.refreshList();
}, (error) => {
alert('Failed');
})
}
updateClick() {
fetch(variables.API_URL + 'employee/updateemployee', {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
EmployeeId: this.state.EmployeeId,
EmployeeName: this.state.EmployeeName,
Department: this.state.Department,
DateOfJoining: this.state.DateOfJoining,
PhotoFileName: this.state.PhotoFileName
})
})
.then(res => res.json())
.then((result) => {
alert(result);
this.refreshList();
}, (error) => {
alert('Failed');
})
}
deleteClick(id) {
if (window.confirm('Are you sure?')) {
fetch(variables.API_URL + 'employee/' + id, {
method: 'DELETE',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then((result) => {
alert(result);
this.refreshList();
}, (error) => {
alert('Failed');
})
}
}
imageUpload = (e) => {
e.preventDefault();
const formData = new FormData();
formData.append("file", e.target.files[0], e.target.files[0].name);
fetch(variables.API_URL + 'employee/savefile', {
method: 'POST',
body: formData
})
.then(res => res.json())
.then(data => {
this.setState({ PhotoFileName: data });
})
}
render() {
const {
departments,
employees,
modalTitle,
EmployeeId,
EmployeeName,
Department,
DateOfJoining,
PhotoPath,
PhotoFileName
} = this.state;
return (
<div>
<button type="button"
className="btn btn-primary m-2 float-end"
data-bs-toggle="modal"
data-bs-target="#exampleModal"
onClick={() => this.addClick()}>
Add Employee
</button>
<table className="table table-striped">
<thead>
<tr>
<th>
Employee Id
</th>
<th>
Employee Name
</th>
<th>
Department
</th>
<th>
DOJ
</th>
<th>
Options
</th>
</tr>
</thead>
<tbody>
{employees.map(emp =>
<tr key={emp.EmployeeId}>
<td>{emp.EmployeeId}</td>
<td>{emp.EmployeeName}</td>
<td>{emp.Department}</td>
<td>{emp.DateOfJoining}</td>
<td>
<button type="button"
className="btn btn-light mr-1"
data-bs-toggle="modal"
data-bs-target="#exampleModal"
onClick={() => this.editClick(emp)}>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-pencil-square" viewBox="0 0 16 16">
<path d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z" />
<path fillRule="evenodd" d="M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0 0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-1H2.5A1.5 1.5 0 0 0 1 2.5v11z" />
</svg>
</button>
<button type="button"
className="btn btn-light mr-1"
onClick={() => this.deleteClick(emp.EmployeeId)}>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-trash-fill" viewBox="0 0 16 16">
<path d="M2.5 1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1H3v9a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4h.5a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H10a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1H2.5zm3 4a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5zM8 5a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7A.5.5 0 0 1 8 5zm3 .5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 1 0z" />
</svg>
</button>
</td>
</tr>
)}
</tbody>
</table>
<div className="modal fade" id="exampleModal" tabIndex="-1" aria-hidden="true">
<div className="modal-dialog modal-lg modal-dialog-centered">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title">{modalTitle}</h5>
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"
></button>
</div>
<div className="modal-body">
<div className="d-flex flex-row bd-highlight mb-3">
<div className="p-2 w-50 bd-highlight">
<div className="input-group mb-3">
<span className="input-group-text">Emp Name</span>
<input type="text" className="form-control"
value={EmployeeName}
onChange={this.changeEmployeeName} />
</div>
<div className="input-group mb-3">
<span className="input-group-text">Department</span>
<select className="form-select"
onChange={this.changeDepartment}
value={Department}>
{departments.map(dep =>
<option key={dep.DepartmentId}>
{dep.DepartmentName}
</option>)}
</select>
</div>
<div className="input-group mb-3">
<span className="input-group-text">DOJ</span>
<input type="date" className="form-control"
value={DateOfJoining}
onChange={this.changeDateOfJoining} />
</div>
</div>
<div className="p-2 w-50 bd-highlight">
<img width="250px" height="250px"
src={PhotoPath + PhotoFileName} />
<input className="m-2" type="file"
onChange={this.imageUpload} />
</div>
</div>
{EmployeeId === 0 ?
<button type="button"
className="btn btn-primary float-start"
onClick={() => this.createClick()}
>Create</button>
: null}
{EmployeeId !== 0 ?
<button type="button"
className="btn btn-primary float-start"
onClick={() => this.updateClick()}
>Update</button>
: null}
</div>
</div>
</div>
</div>
</div>
)
}
}
Now, Open the Home.js file and add code.
import React, { Component } from "react";
export class Home extends Component {
render() {
return(
<div className="mt-5 d-flex justify-content-left">
Home page.
</div>
)
}
}
Now Run the Project using npm start
Home Page
Department
Add Department
Edit Department
Delete Department
Employee
Add Employee
Edit Employee
Delete Employee
Filtering
Now, the same filtering and sorting go for Employee.
I have added the full code as an attachment.