We will see below CRUD operation step by step
On Click on Add button
On Click on Edit button
Need to install some supporting dependencyFolder Structure
Below steps to follow
>npx create-react-app react-redux-crud-operation
>cd react-redux-crud-operation
>code .
>open terminal
>npm i bootstrap
---Then import bootstrap in index.js file
-----import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
>npm i react-router-dom
---Then initiate routing in App.js file
>npm i react-toastify
---Then import bootstrap in index.js file
-----import '../node_modules/react-toastify/dist/ReactToastify.css';
---Then include toast container in App.js file
-----<ToastContainer></ToastContainer>
>npm i redux react-redux redux-thunk axios redux-logger @reduxjs/toolkit
>npm i -g json-server
>json-server --watch src/Data/db.json --port 8000
---Default db.json file will be created with default data --You can modify with your needed..
>npm start
--Start from ActionType>Action>Reducer>Store
--To create json-server
>npm install -g json-server
>json-server --watch src/Data/db.json -p 8000
I. In Data/db.json file and below are code snippets
{
"user": [
{
"id": 1,
"name": "Subs",
"role": "Admin",
"email": "s@p.com",
"phone": "739187391"
},
]
}
II. In Redux/Action.jsx file and below are code snippets
import axios from "axios";
import { ADD_USER, DELETE_USER, FAIL_REQUEST, GET_USER_LIST, GET_USER_OBJ, MAKE_REQUEST, UPDATE_USER } from "./ActionType";
import { toast } from "react-toastify";
export const makeRequest = () => {
return {
type: MAKE_REQUEST,
};
};
export const failRequest = (err) => {
return {
type: FAIL_REQUEST,
payload: err,
};
};
export const getUserList = (data) => {
return {
type: GET_USER_LIST,
payload: data,
};
};
export const deleteUser = () => {
return {
type: DELETE_USER,
};
};
export const addUser = () => {
return {
type: ADD_USER,
};
};
export const updateUser = () => {
return {
type: UPDATE_USER,
};
};
export const getUserObj = (data) => {
return {
type: GET_USER_OBJ,
payload:data
};
};
export const FetchUserList = () => {
return (dispatch) => {
dispatch(makeRequest());
//setTimeout(()=>{
axios
.get("http://localhost:8000/user")
.then((res) => {
const userlist = res.data;
dispatch(getUserList(userlist));
})
.catch((err) => {
dispatch(failRequest(err.message));
})
//},2000)
};
};
export const DeleteUser = (id) => {
return (dispatch) => {
dispatch(makeRequest());
//setTimeout(()=>{
axios
.delete("http://localhost:8000/user/"+id)
.then((res) => {
dispatch(deleteUser());
})
.catch((err) => {
dispatch(failRequest(err.message));
})
//},2000)
};
};
export const AddUser = (data) => {
return (dispatch) => {
dispatch(makeRequest());
//setTimeout(()=>{
axios
.post("http://localhost:8000/user/",data)
.then((res) => {
dispatch(addUser());
toast.success("User added successfully");
})
.catch((err) => {
dispatch(failRequest(err.message));
})
//},2000)
};
};
export const UpdateUser = (data,id) => {
return (dispatch) => {
dispatch(makeRequest());
//setTimeout(()=>{
axios
.put("http://localhost:8000/user/"+id,data)
.then((res) => {
dispatch(updateUser());
toast.success("User update successfully");
})
.catch((err) => {
dispatch(failRequest(err.message));
})
//},2000)
};
};
export const FetchUserObj = (id) => {
return (dispatch) => {
dispatch(makeRequest());
//setTimeout(()=>{
axios
.get("http://localhost:8000/user/"+id)
.then((res) => {
const userlist = res.data;
dispatch(getUserObj(userlist));
})
.catch((err) => {
dispatch(failRequest(err.message));
})
//},2000)
};
};
III. In Redux/ActionType.jsx file and below are code snippets
export const MAKE_REQUEST='MAKE_REQUEST'
export const FAIL_REQUEST='FAIL_REQUEST'
export const GET_USER_LIST='GET_USER_LIST'
export const DELETE_USER='DELETE_USER'
export const ADD_USER='ADD_USER'
export const UPDATE_USER='UPDATE_USER'
export const GET_USER_OBJ='GET_USER_OBJ'
IV. In Redux/Reducer.jsx file and below are code snippets
import { ADD_USER, DELETE_USER, FAIL_REQUEST, GET_USER_LIST, GET_USER_OBJ, MAKE_REQUEST, UPDATE_USER } from "./ActionType"
const initialstate={
loading:true,
userlist:[],
userobj:{},
errmessage:''
}
export const Reducer=(state=initialstate,action)=>{
switch(action.type){
case MAKE_REQUEST:
return{
...state,
loading:true
}
case FAIL_REQUEST:
return{
...state,
loading:false,
errmessage:action.payload
}
case GET_USER_LIST:
return{
loading:false,
errmessage:'',
userlist:action.payload,
userobj:{}
}
case DELETE_USER:
return{
...state,
loading:false
}
case ADD_USER:
return{
...state,
loading:false
}
case UPDATE_USER:
return{
...state,
loading:false
}
case GET_USER_OBJ:
return{
...state,
loading:false,
userobj:action.payload
}
default:return state
}
}
V. In Redux/Store.jsx file and below are code snippets
import { combineReducers, configureStore } from "@reduxjs/toolkit";
import { Reducer } from "./Reducer";
import thunk from "redux-thunk";
import logger from "redux-logger";
const rootreducer=combineReducers({user:Reducer});
const Store=configureStore({reducer:rootreducer,middleware:[thunk,logger]});
export default Store;
VI. In Component/Userlisting.jsx file and below are code snippets
import React, { useEffect } from 'react'
import { DeleteUser, FetchUserList } from '../Redux/Action'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom';
import {toast} from 'react-toastify';
function Userlisting(props) {
useEffect(()=>{
props.loaduser();
},[])
const handleDelete=(id)=>{
if(window.confirm('Do you want to Delete user?')){
props.deleteuser(id);
props.loaduser();
toast.success("User deleted successfully");
}
}
return (
props.user.loading?<div><h2>Loading..</h2></div>:
props.user.errmessage?<div><h2>{props.user.errmessage}</h2></div>:
<div>
<div className='card'>
<div className='card-header'>
<Link to={'/user/add'} className='btn btn-success'>Add User [+]</Link>
</div>
<div className='card-body'>
<table className='table table-bordered'>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th>Role</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{
props.user.userlist && props.user.userlist.map(item=>
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.name}</td>
<td>{item.email}</td>
<td>{item.phone}</td>
<td>{item.role}</td>
<td>
<Link to={`/user/edit/${item.id}`} className='btn btn-primary'>Edit</Link> |
<button onClick={()=>handleDelete(item.id)} className='btn btn-danger'>Delete</button>
</td>
</tr>
)
}
</tbody>
</table>
</div>
</div>
</div>
)
}
const mapStateToProps=(state)=>{
return{
user:state.user
}
}
const mapDispatchToProps=(dispatch)=>{
return{
loaduser:()=>dispatch(FetchUserList()),
deleteuser:(id)=>dispatch(DeleteUser(id))
}
}
export default connect(mapStateToProps,mapDispatchToProps) (Userlisting);
VII. In Component/Adduser.jsx file and below are code snippets
import React, { useState } from 'react'
import { useDispatch } from 'react-redux';
import { Link, useNavigate } from 'react-router-dom'
import { AddUser } from '../Redux/Action';
function Adduser() {
const [name,setname]=useState('');
const [email,setemail]=useState('');
const [phone,setphone]=useState('');
const [role,setrole]=useState('staff');
const dispatch=useDispatch();
const navigate=useNavigate();
const handleSubmit=(e)=>{
e.preventDefault();
const userobj={name,email,phone,role};
console.log(userobj);
dispatch(AddUser(userobj));
navigate('/user');
}
return (
<div>
<form onSubmit={handleSubmit}>
<div className='card'>
<div className='card-header' style={{textAlign:'left'}}>
<h2>Add User</h2>
</div>
<div className='card-body' style={{textAlign:'left'}}>
<div className='row'>
<div className='col-lg-12'>
<div className='form-group'>
<label>Name</label>
<input value={name} onChange={e=>setname(e.target.value)} className='form-control'></input>
</div>
</div>
<div className='col-lg-12'>
<div className='form-group'>
<label>Email</label>
<input value={email} onChange={e=>setemail(e.target.value)} className='form-control'></input>
</div>
</div>
<div className='col-lg-12'>
<div className='form-group'>
<label>Phone</label>
<input value={phone} onChange={e=>setphone(e.target.value)} type='number' className='form-control'></input>
</div>
</div>
<div className='col-lg-12'>
<div className='form-group'>
<label>Role</label>
<input value={role} onChange={e=>setrole(e.target.value)} className='form-control'></input>
</div>
</div>
</div>
</div>
<div className='card-footer' style={{textAlign:'left'}}>
<button className='btn btn-primary' type='submit'>Submit</button> |
<Link to={'/user'} className='btn btn-danger'>Back</Link>
</div>
</div>
</form>
</div>
)
}
export default Adduser
VIII. In Component/Updateuser.jsx file and below are code snippets
import React, { useEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { FetchUserObj, UpdateUser } from '../Redux/Action';
function Updateuser() {
const [code,setcode]=useState('');
const [name,setname]=useState('');
const [email,setemail]=useState('');
const [phone,setphone]=useState('');
const [role,setrole]=useState('staff');
const dispatch=useDispatch();
const navigate=useNavigate();
const {id}= useParams();
const userobj=useSelector((state)=>state.user.userobj);
const handleSubmit=(e)=>{
e.preventDefault();
const userobj={id,name,email,phone,role};
console.log(userobj);
dispatch(UpdateUser(userobj,id));
navigate('/user');
}
useEffect(()=>{
dispatch(FetchUserObj(id));
},[]);
useEffect(()=>{
if(userobj){
setcode(userobj.id);
setname(userobj.name);
setemail(userobj.email);
setphone(userobj.phone);
setrole(userobj.role);
}
},[userobj]);
return (
<div>
<form onSubmit={handleSubmit}>
<div className='card'>
<div className='card-header' style={{textAlign:'left'}}>
<h2>Add User</h2>
</div>
<div className='card-body' style={{textAlign:'left'}}>
<div className='row'>
<div className='col-lg-12'>
<div className='form-group'>
<label>ID</label>
<input value={code || ''} disabled className='form-control'></input>
</div>
</div>
<div className='col-lg-12'>
<div className='form-group'>
<label>Name</label>
<input value={name || ''} onChange={e=>setname(e.target.value)} className='form-control'></input>
</div>
</div>
<div className='col-lg-12'>
<div className='form-group'>
<label>Email</label>
<input value={email || ''} onChange={e=>setemail(e.target.value)} className='form-control'></input>
</div>
</div>
<div className='col-lg-12'>
<div className='form-group'>
<label>Phone</label>
<input value={phone || ''} onChange={e=>setphone(e.target.value)} type='number' className='form-control'></input>
</div>
</div>
<div className='col-lg-12'>
<div className='form-group'>
<label>Role</label>
<input value={role || ''} onChange={e=>setrole(e.target.value)} className='form-control'></input>
</div>
</div>
</div>
</div>
<div className='card-footer' style={{textAlign:'left'}}>
<button className='btn btn-primary' type='submit'>Submit</button> |
<Link to={'/user'} className='btn btn-danger'>Back</Link>
</div>
</div>
</form>
</div>
)
}
export default Updateuser
IX. In Component/Home.jsx file and below are code snippets
import React from 'react'
function Home() {
return (
<div>Home</div>
)
}
export default Home
X. In index.js file and below are code snippets
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import '../node_modules/react-toastify/dist/ReactToastify.css';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
XI. In App.css file and below are code snippets
.header{
width: 100%;
background-color: blue;
color: #fff;
padding: 1%;
text-align: left;
}
a{
text-decoration: none!important;
color: white!important;
padding: 2px;
}
.card-header{
text-align: right;
}
XII. In App.js file and below are code snippets
import logo from './logo.svg';
import './App.css';
import { BrowserRouter, Link, Route, Routes } from 'react-router-dom';
import Home from './Component/Home';
import Userlisting from './Component/Userlisting';
import Adduser from './Component/Adduser';
import Updateuser from './Component/Updateuser';
import { ToastContainer } from 'react-toastify';
import { Provider } from 'react-redux';
import Store from './Redux/Store';
function App() {
return (
<Provider store={Store}>
<div className="App">
<BrowserRouter>
<div className='header'>
<Link to={'/'}>Home</Link>
<Link to={'/user'}>User</Link>
</div>
<Routes>
<Route path='/' element={<Home></Home>}></Route>
<Route path='/user' element={<Userlisting></Userlisting>}></Route>
<Route path='/user/add' element={<Adduser></Adduser>}></Route>
<Route path='/user/edit/:id' element={<Updateuser></Updateuser>}></Route>
</Routes>
</BrowserRouter>
<ToastContainer position='bottom-right'></ToastContainer>
</div>
</Provider>
);
}
export default App;
No comments:
Post a Comment