To create a fully functional React CRUD application that mirrors the design in the provided image, we will follow these steps:
Setup the React Project:
- Create a new React app using Create React App.
- Install necessary dependencies such as axios for HTTP requests, json-server for mock API, and react-router-dom for navigation.
Setup JSON Server:
- Create a
db.json
file with dummy data. - Configure json-server to serve this file.
- Create a
App Structure:
- Components:
App
,EmployeeList
,AddEmployee
,UpdateEmployee
,ViewEmployee
,DeleteEmployee
,Navbar
. - Use React Router for navigation between components.
- Components:
Local Storage Integration:
- Sync CRUD operations with local storage to persist data.
CSS Styling:
- Apply CSS to achieve the design shown in the provided image.
Documentation and Code Comments:
- Provide comments and explanations for each code block.
Let’s start by outlining the folder structure and creating the basic files:
Folder Structure:
react-crud-app/
|-- public/
|-- src/
| |-- components/
| | |-- AddEmployee.js
| | |-- UpdateEmployee.js
| | |-- ViewEmployee.js
| | |-- DeleteEmployee.js
| | |-- EmployeeList.js
| | |-- Navbar.js
| |-- App.js
| |-- index.js
| |-- App.css
|-- db.json
|-- package.json
Step 1: Setting Up the React Project
First, create a new React app:
npx create-react-app react-crud-app
cd react-crud-app
npm install axios react-router-dom@6
Step 2: Setting Up JSON Server
Create a db.json
file in the root of your project:
{
"employees": [
{ "id": 1, "firstName": "Ramesh", "lastName": "Fadatare", "email": "ram@gmail.com" },
{ "id": 2, "firstName": "John", "lastName": "Cena", "email": "john@gmail.com" },
{ "id": 3, "firstName": "Tom", "lastName": "Cruise", "email": "tom@gmail.com" },
{ "id": 4, "firstName": "Admin", "lastName": "admin", "email": "admin@gmail.com" }
]
}
Install and run json-server:
npm install -g json-server
json-server --watch db.json --port 5000
Step 3: Creating Components
Create the following component files with initial structure:
src/components/EmployeeList.js:
import React, { useState, useEffect } from 'react'; // Import necessary hooks from React
import axios from 'axios'; // Import axios for making HTTP requests
import { Link } from 'react-router-dom'; // Import Link for navigation
const EmployeeList = () => {
const [employees, setEmployees] = useState([]); // State to hold the list of employees
// useEffect hook to fetch employees data from the server when the component mounts
useEffect(() => {
axios.get('http://localhost:5000/employees') // Make GET request to fetch employees
.then(response => {
setEmployees(response.data); // Set the employees state with the fetched data
})
.catch(error => console.log(error)); // Log any error
}, []); // Empty dependency array means this effect runs only once when the component mounts
return (
<div className="employee-list">
<h2>Employees List</h2>
<Link to="/add" className="btn btn-primary">Add Employee</Link> {/* Link to AddEmployee component */}
<table className="table">
<thead>
<tr>
<th>Employee First Name</th>
<th>Employee Last Name</th>
<th>Employee Email Id</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{employees.map(employee => (
<tr key={employee.id}>
<td>{employee.firstName}</td>
<td>{employee.lastName}</td>
<td>{employee.email}</td>
<td>
<Link to={`/update/${employee.id}`} className="btn btn-info">Update</Link> {/* Link to UpdateEmployee component */}
<Link to={`/delete/${employee.id}`} className="btn btn-danger">Delete</Link> {/* Link to DeleteEmployee component */}
<Link to={`/view/${employee.id}`} className="btn btn-success">View</Link> {/* Link to ViewEmployee component */}
</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default EmployeeList;
src/components/AddEmployee.js:
import React, { useState } from 'react'; // Import necessary hooks from React
import axios from 'axios'; // Import axios for making HTTP requests
import { useNavigate } from 'react-router-dom'; // Import useNavigate for navigation
const AddEmployee = () => {
const [employee, setEmployee] = useState({ firstName: '', lastName: '', email: '' }); // State to hold the new employee data
const navigate = useNavigate(); // Initialize useNavigate for navigation
// Handle change in input fields
const handleChange = (e) => {
const { name, value } = e.target;
setEmployee({ ...employee, [name]: value });
};
// Handle form submission
const handleSubmit = (e) => {
e.preventDefault();
axios.post('http://localhost:5000/employees', employee) // Make POST request to add employee
.then(response => {
navigate('/'); // Navigate back to the employee list after adding
})
.catch(error => console.log(error)); // Log any error
};
return (
<div className="add-employee">
<h2>Add Employee</h2>
<form onSubmit={handleSubmit}>
<div className="form-group">
<label>First Name</label>
<input type="text" name="firstName" value={employee.firstName} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Last Name</label>
<input type="text" name="lastName" value={employee.lastName} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Email</label>
<input type="email" name="email" value={employee.email} onChange={handleChange} required />
</div>
<button type="submit" className="btn btn-primary">Add</button>
</form>
</div>
);
};
export default AddEmployee;
src/components/UpdateEmployee.js:
import React, { useState, useEffect } from 'react'; // Import necessary hooks from React
import axios from 'axios'; // Import axios for making HTTP requests
import { useParams, useNavigate } from 'react-router-dom'; // Import useParams and useNavigate for navigation and params
const UpdateEmployee = () => {
const { id } = useParams(); // Get the employee ID from the URL parameters
const [employee, setEmployee] = useState({ firstName: '', lastName: '', email: '' }); // State to hold the employee data
const navigate = useNavigate(); // Initialize useNavigate for navigation
// useEffect hook to fetch employee data from the server when the component mounts
useEffect(() => {
axios.get(`http://localhost:5000/employees/${id}`) // Make GET request to fetch employee
.then(response => {
setEmployee(response.data); // Set the employee state with the fetched data
})
.catch(error => console.log(error)); // Log any error
}, [id]); // Dependency array with id means this effect runs when the id changes
// Handle change in input fields
const handleChange = (e) => {
const { name, value } = e.target;
setEmployee({ ...employee, [name]: value });
};
// Handle form submission
const handleSubmit = (e) => {
e.preventDefault();
axios.put(`http://localhost:5000/employees/${id}`, employee) // Make PUT request to update employee
.then(response => {
navigate('/'); // Navigate back to the employee list after updating
})
.catch(error => console.log(error)); // Log any error
};
return (
<div className="update-employee">
<h2>Update Employee</h2>
<form onSubmit={handleSubmit}>
<div className="form-group">
<label>First Name</label>
<input type="text" name="firstName" value={employee.firstName} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Last Name</label>
<input type="text" name="lastName" value={employee.lastName} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Email</label>
<input type="email" name="email" value={employee.email} onChange={handleChange} required />
</div>
<button type="submit" className="btn btn-primary">Update</button>
</form>
</div>
);
};
export default UpdateEmployee;
src/components/ViewEmployee.js:
import React, { useState, useEffect } from 'react'; // Import necessary hooks from React
import axios from 'axios'; // Import axios for making HTTP requests
import { useParams } from 'react-router-dom'; // Import useParams for getting the URL parameter
const ViewEmployee = () => {
const { id } = useParams(); // Get the employee ID from the URL parameters
const [employee, setEmployee] = useState({ firstName: '', lastName: '', email: '' }); // State to hold the employee data
// useEffect hook to fetch employee data from the server when the component mounts
useEffect(() => {
axios.get(`http://localhost:5000/employees/${id}`) // Make GET request to fetch employee
.then(response => {
setEmployee(response.data); // Set the employee state with the fetched data
})
.catch(error => console.log(error)); // Log any error
}, [id]); // Dependency array with id means this effect runs when the id changes
return (
<div className="view-employee">
<h2>View Employee</h2>
<p>First Name: {employee.firstName}</p>
<p>Last Name: {employee.lastName}</p>
<p>Email: {employee.email}</p>
</div>
);
};
export default ViewEmployee;
src/components/DeleteEmployee.js:
import React, { useEffect } from 'react'; // Import necessary hooks from React
import axios from 'axios'; // Import axios for making HTTP requests
import { useParams, useNavigate } from 'react-router-dom'; // Import useParams and useNavigate for navigation and params
const DeleteEmployee = () => {
const { id } = useParams(); // Get the employee ID from the URL parameters
const navigate = useNavigate(); // Initialize useNavigate for navigation
// useEffect hook to delete employee data from the server when the component mounts
useEffect(() => {
axios.delete(`http://localhost:5000/employees/${id}`) // Make DELETE request to delete employee
.then(response => {
navigate('/'); // Navigate back to the employee list after deleting
})
.catch(error => console.log(error)); // Log any error
}, [id, navigate]); // Dependency array with id and navigate means this effect runs when the id or navigate changes
return (
<div className="delete-employee">
<h2>Deleting Employee...</h2>
</div>
);
};
export default DeleteEmployee;
src/components/Navbar.js:
import React from 'react'; // Import React
import { Link } from 'react-router-dom'; // Import Link for navigation
const Navbar = () => {
return (
<nav className="navbar">
<h1>Employee Management App</h1>
<div className="links">
<Link to="/">Home</Link> {/* Link to EmployeeList component */}
<Link to="/add">Add Employee</Link> {/* Link to AddEmployee component */}
</div>
</nav>
);
};
export default Navbar;
src/App.js:
import React from 'react'; // Import React
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'; // Import BrowserRouter, Routes, and Route for routing
import Navbar from './components/Navbar'; // Import Navbar component
import EmployeeList from './components/EmployeeList'; // Import EmployeeList component
import AddEmployee from './components/AddEmployee'; // Import AddEmployee component
import UpdateEmployee from './components/UpdateEmployee'; // Import UpdateEmployee component
import ViewEmployee from './components/ViewEmployee'; // Import ViewEmployee component
import DeleteEmployee from './components/DeleteEmployee'; // Import DeleteEmployee component
import './App.css'; // Import CSS file for styling
function App() {
return (
<Router>
<div className="App">
<Navbar /> {/* Render Navbar component */}
<div className="content">
<Routes>
<Route exact path="/" element={<EmployeeList />} /> {/* Route for EmployeeList component */}
<Route path="/add" element={<AddEmployee />} /> {/* Route for AddEmployee component */}
<Route path="/update/:id" element={<UpdateEmployee />} /> {/* Route for UpdateEmployee component */}
<Route path="/view/:id" element={<ViewEmployee />} /> {/* Route for ViewEmployee component */}
<Route path="/delete/:id" element={<DeleteEmployee />} /> {/* Route for DeleteEmployee component */}
</Routes>
</div>
</div>
</Router>
);
}
export default App;
src/App.css:
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.navbar {
background-color: #333;
color: #fff;
padding: 10px 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.navbar h1 {
margin: 0;
}
.navbar .links a {
color: #fff;
margin-left: 20px;
text-decoration: none;
}
.btn {
padding: 5px 10px;
margin: 0 5px;
border: none;
color: #fff;
cursor: pointer;
}
.btn-primary {
background-color: #007bff;
}
.btn-info {
background-color: #17a2b8;
}
.btn-danger {
background-color: #dc3545;
}
.btn-success {
background-color: #28a745;
}
.table {
width: 100%;
margin: 20px 0;
border-collapse: collapse;
}
.table th, .table td {
padding: 10px;
border: 1px solid #ddd;
text-align: left;
}
.table th {
background-color: #f8f8f8;
}
.form-group {
margin: 10px 0;
}
.form-group label {
display: block;
margin-bottom: 5px;
}
.form-group input {
width: 100%;
padding: 8px;
box-sizing: border-box;
}
Welcome to DevTechTutor.com, your ultimate resource for mastering web development and technology! Whether you're a beginner eager to dive into coding or an experienced developer looking to sharpen your skills, DevTechTutor.com is here to guide you every step of the way. Our mission is to make learning web development accessible, engaging, and effective.