You are currently viewing Build a CRUD App with React.js and Redux Toolkit for Beginners | “React Redux CRUD App”
Build a CRUD App with React.js and Redux Toolkit for Beginners | "React Redux CRUD App"

Build a CRUD App with React.js and Redux Toolkit for Beginners | “React Redux CRUD App”

You will use Redux Toolkit to build React.js CRUD application by following this detailed tutorial. React Redux CRUD Application for Beginners [With Hooks]. An example how to build React Redux CRUD application.

You will get a comprehensive tutorial covering all the aspects related to React, Redux-Toolkit, Bootstrap, React-Router-DOM, and Axios. Lets Build a CRUD App with React.js and Redux Toolkit for Beginners

Folder Structure

Lets write index.js code so where i have paste bootstrap links so that you can use bootstrap components .

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" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
  </body>
</html>

Now lets Write index.js file where we have a binding store and provider through which we can extract the data in our components .

Index.js

import React from 'react';
import { configureStore } from '@reduxjs/toolkit';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';

import {Provider} from 'react-redux'
import UserReducer from './redux/UserReducer';

const store = configureStore({
  reducer:{
    // here user is a variable 
    //UserReducer in which data is reside .
    users:UserReducer
  }
})

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </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();

// step 1 

// Provider

Now lets Jump into App.js where we have perform routing for different pages like Craete page update page through which we are binding the logics .

APP.JS

import React from 'react';
import { configureStore } from '@reduxjs/toolkit';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';

import {Provider} from 'react-redux'
import UserReducer from './redux/UserReducer';

const store = configureStore({
  reducer:{
    // here user is a variable 
    //UserReducer in which data is reside .
    users:UserReducer
  }
})

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);



Data.jsx

export const userList = [
    {
        name:"Test",
        email:"test@gmail.com",
        id:1
    },
    {
        name:"Tinku",
        email:"tinku@gmail.com",
        id:2
    }
]

useReducer.js

here we have write the logic for add delete and update the data . With this reducer you can understand all the senario of crud app how we can handle and how we can apply logic for these type of application .

import { createSlice } from "@reduxjs/toolkit";
import { userList } from "../Data";

const userSlice = createSlice({
    name: "users",
    initialState: userList,
    reducers: {
        addUser: (state, action) => {
            console.log("Action user", action);
            state.push(action.payload);           
        },

        updateUser: (state, action) => {
            const { id, name, email } = action.payload;
            const uu = state.find(user => user.id == id);
            if (uu) {
                uu.name = name;
                uu.email = email;
            }
        },
        
        deleteUser: (state, action) => {
            const { id } = action.payload;
            return state.filter(user => user.id !== id);
        }
    }
});

export const { addUser, updateUser, deleteUser } = userSlice.actions;
export default userSlice.reducer;

Now lets move into components part where we have to make componets for craete update and delete .

Create.js

import React, { useState } from 'react'
import { useDispatch, useSelector } from "react-redux";
import { addUser } from '../redux/UserReducer';
import { useNavigate } from 'react-router-dom';


const Create = () => {
    const [name,setName] = useState('')
    const [email,setEmail] = useState('')
    const users = useSelector((state) => state.users)
    const dispatch = useDispatch();
    const navigate = useNavigate()

    const handleSubmit = (e) => {
        e.preventDefault();
        dispatch(addUser({id:users[users.length - 1].id+1,name,email}))
        navigate('/')


    }

    return (
        <div className='d-flex w-100 vh-50 justify-content-center align-item-center mt-5'>
            <div className='w-50 border bg-secondary text-white p-5'>
                <h3>Add New User</h3>
                <form onSubmit={handleSubmit}>
                    <div>
                        <label htmlFor='name'>Name:</label>
                        <input type='text' name='name' className='form-control' placeholder='Enter name' onChange={e=>setName(e.target.value)} />
                    </div>
                    <div>
                        <label htmlFor='email'>Email:</label>
                        <input type='email' name='email' className='form-control' placeholder='Enter email' onChange={(e)=>setEmail(e.target.value)} />
                    </div>
                    <br/>
                    <button className='btn btn-info'>Submit</button>
                </form>
            </div>
        </div>
    )
}

export default Create

Home.js

import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Link, useNavigate } from 'react-router-dom';

const Home = () => {
    const users = useSelector((state) => state.users);
    const dispatch = useDispatch();
    console.log(users);
    const navigate = useNavigate()
    return (
        <div className='container' style={{marginTop:'10rem'}}>
            <h2>Crud App With JSON Server</h2>
            <Link to="/create" className='btn btn-success ny-3'>Create +</Link>
            <table className='table'>
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>Name</th>
                        <th>Email</th>
                        <th>Action</th>
                    </tr>
                </thead>
                <tbody>
                    {users.map((users, index) => (
                        <tr key={index}>
                            <td>{users.id}</td>
                            <td>{users.name}</td>
                            <td>{users.email}</td>
                            <td>
                                <Link to={`/edit/${users.id}`}  className='btn btn-sm btn-primary'>Edit</Link>
                                <Link onChange={() => handleDelet(user.id)} className='btn btn-sm btn-danger ms-2'>Delete</Link>
                            </td>
                        </tr>
                    ))}           
                </tbody>
            </table>
        </div>
    )
}

export default Home

Update.js

import React, { useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
// import { useSelector } from 'react-redux';
import { useDispatch, useSelector } from "react-redux";
import { updateUser } from '../redux/UserReducer';

const Update = () => {
    const { id } = useParams();
    const users = useSelector((state) => state.users);
    const existingUser = users.find((user) => user.id == id);

    const [uname, setName] = useState(existingUser ? existingUser.name : '');
    const [uemail, setEmail] = useState(existingUser ? existingUser.email : '');
    const dispatch = useDispatch();
    const navigate = useNavigate();

    const handleUpdate = (event) => {
        event.preventDefault();
        dispatch(
            updateUser({
                id: id,
                name: uname,
                email: uemail
            }))
            navigate('/')
        
    }

    return (
        <div className='d-flex w-100 vh-50 justify-content-center align-items-center mt-5'>
            <div className='w-50 border bg-secondary text-white p-5'>
                <h3>Update User</h3>
                <form onSubmit={handleUpdate}>
                    <div>
                        <label htmlFor='name'>Name:</label>
                        <input
                            type='text'
                            name='name'
                            value={uname}
                            className='form-control'
                            placeholder='Enter name'
                            onChange={(e) => setName(e.target.value)}
                        />
                    </div>
                    <div>
                        <label htmlFor='email'>Email:</label>
                        <input
                            type='email'
                            name='email'
                            value={uemail}
                            className='form-control'
                            placeholder='Enter email'
                            onChange={(e) => setEmail(e.target.value)}
                        />
                    </div>
                    <br />
                    <button className='btn btn-info'>Update</button>
                </form>
            </div>
        </div>
    );
}

export default Update;

Package.js

{
  "name": "redux_project",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@reduxjs/toolkit": "^2.2.7",
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "bootstrap": "^5.3.3",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-redux": "^9.1.2",
    "react-router-dom": "^6.25.1",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Conclusion

I hope you enjoyed this little tutorial. Let me know over on comment and please give me suggestion regarding it which type of content you want. Hope you are comfortable with this tutorial if you kindly comment in the comment box if you are facing any issues with it. Google Login Form Design using HTML & CSS.

Happy Coding! ?

People are also reading: