Thursday 30 November 2023

CRUD operation using React Redux Class Component

 We will see below CRUD operation step by step

On Click Add button

On Click Edit button
Folder Structure
Need to install some supporting dependency

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",
      "email": "s@p.com",
      "phone": "7391873910",
      "role": "Staff"
    },
]
}

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";

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());
        })
        .catch((err) => {
          dispatch(failRequest(err.message));
        })
 
      //},2000)
    };
  };
 
  export const UpdateUser = (id,data) => {
    return (dispatch) => {
      dispatch(makeRequest());
      //setTimeout(()=>{
 
      axios
        .put("http://localhost:8000/user/"+id,data)
        .then((res) => {
          dispatch(updateUser());
        })
        .catch((err) => {
          dispatch(failRequest(err.message));
        })
 
      //},2000)
    };
  };

  export const GetUserObj = (id) => {
    return (dispatch) => {
      dispatch(makeRequest());
      //setTimeout(()=>{
 
      axios
        .get("http://localhost:8000/user/"+id)
        .then((res) => {
          const userobj = res.data;
          dispatch(getUserObj(userobj));
        })
        .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='DELETE_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{
                ...state,
                loading:false,
                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({users: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, { Component } from 'react'
import { Link } from 'react-router-dom'
import { DeleteUser, FetchUserList } from '../Redux/Action';
import { connect } from 'react-redux';
import { toast } from 'react-toastify';

export class Userlisting extends Component {
    constructor(props){
        super(props);

        this.state={};
    }
   
    componentDidMount(){
        this.props.loaduser();
    }

    handleDelete=(id)=>{
        if(window.confirm('Do you want to Delete user?')){
          this.props.deleteuser(id);
          this.props.loaduser();
          toast.success("User deleted successfully");
        }
    }

  render() {
    return (
      <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>
            {
              this.props.users.userlist && this.props.users.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={()=>this.handleDelete(item.id)} className='btn btn-danger'>Delete</button>
                  </td>
                </tr>
                )
            }

          </tbody>

        </table>
      </div>
    </div>
</div>
    )
  }
}

const mapStateToProps=(state)=>{
    return{
      users:state.users
    }
  }
 
  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, { Component } from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import { AddUser } from '../Redux/Action'
import Userlisting from './Userlisting'

export class Adduser extends Component {
    constructor(props){
        super(props)
        this.state={
            name:'',
            email:'',
            phone:'',
            role:'Staff',
        }
       
    }

    handleSubmit=(e)=>{
        e.preventDefault();
        const {name,email,phone,role}=this.state;
        const userobj={name,email,phone,role};
        console.log(userobj);
        this.props.adduser(userobj);
    }

    getData=(e)=>{
        this.setState({[e.target.name]:e.target.value});
    }

  render() {
    return (
        <div>
        <form onSubmit={this.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 name='name' value={this.name} onChange={this.getData} type='text' className='form-control'></input>
                            </div>
                        </div>
                        <div className='col-lg-12'>
                            <div className='form-group'>
                                <label>Email</label>
                                <input name='email' value={this.email} onChange={this.getData} type='email' className='form-control'></input>
                            </div>
                        </div>
                        <div className='col-lg-12'>
                            <div className='form-group'>
                                <label>Phone</label>
                                <input name='phone' value={this.phone} onChange={this.getData} type='number' className='form-control'></input>
                            </div>
                        </div>
                        <div className='col-lg-12'>
                            <div className='form-group'>
                                <label>Role</label>
                                <input name='role' value={this.role} onChange={this.getData} type='text' className='form-control'></input>
                            </div>
                        </div>

                    </div>
                </div>
                <div className='card-footer'>
                    <button type='submit' className='btn btn-primary'>Submit</button>
                    <Link to={'/user'} className='btn btn-danger'>Back</Link>
                </div>

            </div>
        </form>
      </div>
    )
  }
}

const mapDispatchToProps=(dispatch)=>{
    return{
      adduser:(data)=>dispatch(AddUser(data)),
    }
  }

  export default connect(null,mapDispatchToProps) (Adduser);

VIII. In Component/Updateuser.jsx file and below are code snippets
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import { GetUserObj, UpdateUser } from '../Redux/Action'

export class Updateuser extends Component {
    constructor(props){
        super(props)
        this.state={
            id:0,
            name:'',
            email:'',
            phone:'',
            role:'staff',
            userobj:{}
        }
        console.log(props);
    }

    getData=(e)=>{
        this.setState({[e.target.name]:e.target.value});
    }

    componentDidMount(){
        const id = window.location.href.split('/')[5];
        this.props.loaduserobj(id);
        //This is not working--means state is not assigned
        this.setState({[this.state]:this.props.userobj});
        console.log(this.props.userobj.id);
        console.log(this.props.userobj.name);
        console.log(this.props.userobj.email);
        console.log(this.props.userobj.phone);
        console.log(this.props.userobj.role);
        console.log('above r prop data');
        if(this.props.userobj){
            console.log('userobj');
            this.setState({id:this.props.userobj.id});
            this.setState({name:this.props.userobj.name});
            this.setState({email:this.props.userobj.email});
            this.setState({phone:this.props.userobj.phone});
            this.setState({role:this.props.userobj.role});

            //This is not working--means state is not assigned
            console.log(this.state.name);
        }
       
    }

    handleSubmit=(e)=>{
        e.preventDefault();
        const {id,name,email,phone,role}=this.state;
        const userobj={id,name,email,phone,role};
        console.log(userobj);
        this.props.updateuser(id,userobj);
    }

  render() {
    const {id,name,email,phone,role}=this.state;
   
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
            <div className='card'>
                <div className='card-header' style={{textAlign:'left'}}>
                    <h2>Update 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 name='id' value={id} onChange={this.getData} type='text' disabled className='form-control'></input>
                            </div>
                        </div>
                        <div className='col-lg-12'>
                            <div className='form-group'>
                                <label>Name</label>
                                <input name='name' value={name} onChange={this.getData} type='text' className='form-control'></input>
                            </div>
                        </div>
                        <div className='col-lg-12'>
                            <div className='form-group'>
                                <label>Email</label>
                                <input name='email' value={email} onChange={this.getData}  type='email' className='form-control'></input>
                            </div>
                        </div>
                        <div className='col-lg-12'>
                            <div className='form-group'>
                                <label>Phone</label>
                                <input name='phone' value={phone} onChange={this.getData}  type='number' className='form-control'></input>
                            </div>
                        </div>
                        <div className='col-lg-12'>
                            <div className='form-group'>
                                <label>Role</label>
                                <input name='role' value={role} onChange={this.getData}  type='text' className='form-control'></input>
                            </div>
                        </div>

                    </div>
                </div>
                <div className='card-footer'>
                    <button type='submit' className='btn btn-primary'>Submit</button>
                    <Link to={'/user'} className='btn btn-danger'>Back</Link>
                </div>

            </div>
        </form>
      </div>
    )
  }
}

const mapStateToProps=(state)=>{
    return{
        userobj:state.users.userobj
    }
  }

const mapDispatchToProps=(dispatch)=>{
    return{
      updateuser:(id,data)=>dispatch(UpdateUser(id,data)),
      loaduserobj:(id)=>dispatch(GetUserObj(id)),
    }
  }

export default connect(mapStateToProps,mapDispatchToProps) (Updateuser);

IX. In Component/Home.jsx file and below are code snippets
import React, { Component } from 'react'

export default class Home extends Component {
  render() {
    return (
      <div>Home</div>
    )
  }
}

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 React, { Component } from 'react'
import { BrowserRouter, Link, Route, Routes, useNavigate } 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';

export class App extends Component {
  render(){
  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></ToastContainer>
    </div>
    </Provider>
  );
}
}

export default App;

No comments:

Post a Comment