How to perform CRUD operation in React

Posted by

CRUD consists of four functions that are Create, Read, Update and Delete and it is the most basic operation of a web application. The create function allows the client to create a new record whereas the read function allows the client to get particular data. The other function named update is used to update the data and finally, the delete function is used to delete the data. This operation is the fundamental base that is widely used in web applications.

In this tutorial, We are going to create a simple Contact list where a user can create a contact, see the created contact, edit it and delete it. If you notice, then you may be able to see that, by performing these actions we are completing the four functions of CRUD and at the end of this tutorial you can perform CRUD operations on your own in React Moreover, this tutorial is going to help you to connect the dots of your fundamental concepts in React that you have learned previously.

Prerequisite

Before jumping into the main section of this tutorial, you need to keep these below things in your mind.

  • A configured computer with an internet connection.
  • Basic knowledge of JavaScript, HTML, and CSS.
  • A text editor – You can choose any text editor on which you may write JavaScript code such as sublime text, nodepad++, etc. In this tutorial, we will use visual studio code.
  • Installed NPM on your computer. We are using NPM version v8.7.0.
  • Clear concept on fundamental topics of ReactJS.

Having these things will bring the best outcome from the tutorial for you. Let’s see the topics that will be covered in this tutorial.

Things You will learn from this tutorial

We will cover the following topics in this tutorial and the topic’s names are given in the below section:

  • Environment setup for React Application
  • Create Add Contact Functionality
  • Create Get Contact Functionality
  • Create Edit Contact Functionality
  • Create Delete Contact Functionality and Context
  • Create different Routes
  • Output

Environment setup for React Application

To work in any React application, at first we need to set up the environment for it. To do so, we need to write the below command that will create a demo react app for us. See the below command:

npx create-react-app .

This command will install react and its necessary packages in our specified folder. The npx create-react-app is doing all the stuff for us. We have just recognized our directory name with a “dot(.)” It will take some time to install all the packages depending on the internet connection. Make sure that you have connected your computer to the internet.

You will see some files like the below image after the installation process has been finished. This may be different from yours because we have removed some unnecessary stuffs from this.

We need to install a few more packages to work smoothly in this application. Such as react-router for handling routes and bootstrap and reactstrap for styling. uuid for generating a unique id. To install these follow the below commands:

npm i uuid react-router-dom reactstrap bootstrap

Now, we are ready to make our hands dirty with the code. In the next section, we are going to implement our CRUD application features one by one.

Create Add Contact Functionality

In this stage, we will create the functionality for adding new Contact. To perform this action, we will create a folder named components first and inside that folder, we will create a component file named AddContact.js See the below code example first:

import React, { useState, useContext } from 'react';
import { GlobalContext } from "../context/GlobalState";
import { v4 as uuid } from "uuid";
import { Link, useNavigate } from "react-router-dom";
import {
  Form,
  FormGroup,
  Label,
  Input,
  Button
} from "reactstrap";

export const AddContact = () => {
  const [name, setName] = useState('');
  const { addContact } = useContext(GlobalContext);
  const navigate = useNavigate();

  const onSubmit = (e) => {
    e.preventDefault();
    const newContact = {
      id: uuid(),
      name
    }
    addContact(newContact);
    navigate("/");
  
  }

  const onChange = (e) => {
    setName(e.target.value);
  }

  return (
    <Form onSubmit={onSubmit}>
      <FormGroup>
        <Label>Contact No:</Label>
        <Input type="text" value={name} onChange={onChange} name="name" placeholder="Enter Contact" required></Input>
      </FormGroup>
      <Button type="submit">Save</Button>
      <Link to="/" className="btn btn-danger ml-2">Delete</Link>
    </Form>
  )
}

Here, you can see that we have used uuid to generate a unique id the moment a new contact list has been created. We have used useState and useContext to hold the state of the data so that we can change them later. We have also created a GlobalContext file where we handle the context globally. We will see the implementation later.

Finally, in the returned function, we have used these functions in the input field and a button to save the contact. Let’s implement the Get contact functionality in the next section.

Create Get Contact Functionality

In this stage, we will handle the Get contact functionality which is the second function of the CRUD operation. That means we will read our created data. To do so, we will create a component file inside the components folder and name it ContactList.js After creating the file, we will write our code. See the below code example for it:

import React, { useContext } from 'react';
import { GlobalContext } from "../context/GlobalState";
import { Link } from "react-router-dom";
import {
  ListGroup,
  ListGroupItem,
  Button
} from "reactstrap";

export const ContactList = () => {
  const { contacts, removeContact } = useContext(GlobalContext);

  return (
    <ListGroup className="mt-4">
      {contacts.length > 0 ? (
        <>
          {contacts.map(contact => (
            <ListGroupItem className="d-flex" key={contact.id}>
              <strong>{contact.name}</strong>
              <div className="ml-auto">
                <Link to={`/edit/${contact.id}`} color="warning" className="btn btn-warning mr-1">Edit</Link>
                <Button onClick={() => removeContact(contact.id)} color="danger">Delete</Button>
              </div>
            </ListGroupItem>
          ))}
        </>
      ) : (
          <h4 className="text-center">No contacts</h4>
        )}
    </ListGroup>
  )
}

Here, at first, we have imported the GlobalContext file from the context folder, and later on, simply check if our length of the contact list is greater than 0 or not. If it is greater than 0 that means there’s some data has been stored. All we need to do is to read that data. To do so, we simply perform a map operation and show our data in the output nicely. If it does not find any data then it simply shows us a No Contacts message.

We have also implemented the functionality of Delete contact here.

Create Edit Contact Functionality

After visualizing the data, now it’s time to create an Edit functionality in our application. To perform this action, like before, we will create a component file in our components folder and name it EditContact.js See the below code example of the implementation:

import React, { useState, useContext, useEffect } from 'react';
import { GlobalContext } from "../context/GlobalState";
import { Link, useNavigate } from "react-router-dom";
import {
  Form,
  FormGroup,
  Label,
  Input,
  Button
} from "reactstrap";

export const EditContact = (props) => {
  const { EditContact, contacts } = useContext(GlobalContext);
  const [selectedContact, setSelectedContact] = useState({
    id: '',
    name: ''
  })
  const navigate = useNavigate();
  const currentContactId = props.id

  useEffect(() => {
    const contactId = currentContactId;
    const selectedContact = contacts.find(contact => contact.id === contactId);
    setSelectedContact(selectedContact);
  }, [currentContactId, contacts])

  const onChange = (e) => {
    setSelectedContact({ ...selectedContact, [e.target.name]: e.target.value })
  }

  const onSubmit = (e) => {
    e.preventDefault();
    EditContact(selectedContact);
    navigate("/")
  }

  return (
    <Form onSubmit={onSubmit}>
      <FormGroup>
        <Label>Contact No</Label>
        <Input type="text" onChange={onChange} name="name" placeholder="Enter Contact" required></Input>
      </FormGroup>
      <Button type="submit">Edit Contact</Button>
      <Link to="/" className="btn btn-danger ml-2">Cancel</Link>
    </Form>
  )
}

Here, the user will want to update a single data at a single time. But we don’t know which data the user wants to update. To do so, at first we have caught the id number that a user wants to change and then implement the functionality for updating.

We have also cross-checked whether the id number that a user has been provided already exists in our program or not. If it matches then simply let the user change the data otherwise not. We have also set this field required so that the user does not keep it empty.

Create Delete Contact Functionality and Context

We have implemented the delete functionality while creating the get contact functionality. You do not need to do an extra thing for this. But if you notice, you may be able to see that, almost every place we have used the GlobalContext because of holding our Data. Let’s see the implementation of these.

To do so, we have created a separate folder into our src folder and named it the context folder. Let me assume that you have already known about the term context in react. In this tutorial, we will not explain it.

In the context folder, we have created two files named AppReducer.js and GlobalContext.js See the implementation of them in the below code example:

// App Reducer
// eslint-disable-next-line import/no-anonymous-default-export
export default (state, action) => {
    switch (action.type) {
        case 'REMOVE_CONTACT':
            return {
            ...state,
            contacts: state.contacts.filter(user => {
                return user.id !== action.payload;
            })
        }
        case 'ADD_CONTACT':
            return {
            ...state,
            contacts: [action.payload, ...state.contacts]
        }
        case 'EDIT_CONTACT':
            const updateContact = action.payload;

            const updateContacts = state.contacts.map(contact => {
            if (contact.id === updateContact.id) {
            return updateContact;
            }
            return contact;
        })
            return {
            ...state,
            contacts: updateContacts
        }
  
        default:
            return state;
        }
    }
// Global Context
import React, { createContext, useReducer } from 'react';
import AppReducer from './AppReducer';

// Initial State
const initialState = {
  contacts: []
}

// Create Context
export const GlobalContext = createContext(initialState);

// Provider Component
export const GlobalProvider = ({ children }) => {
  const [state, dispatch] = useReducer(AppReducer, initialState);

  // Actions
  const removeContact = (id) => {
    dispatch({
      type: 'REMOVE_CONTACT',
      payload: id
    })
  }

  const addContact = (contact) => {
    dispatch({
      type: 'ADD_CONTACT',
      payload: contact
    })
  }

  const editContact = (contact) => {
    dispatch({
      type: 'EDIT_CONTACT',
      payload: contact
    })
  }

  return (
    <GlobalContext.Provider value={{
      contacts: state.contacts,
      removeContact,
      addContact,
      editContact
    }}>
      {children}
    </GlobalContext.Provider>
  )
}

Create different Routes

After implementing all of these, now it’s time to handle separate routes for each of our components. We will perform this action in our App.js file which is considered the main entry point of our application. See the below code example of performing this action:

import React from 'react';
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import { Home } from "./components/Home";
import { AddContact } from "./components/AddContact";
import { EditContact } from "./components/EditContact";
import { GlobalProvider } from "./context/GlobalState";

import "bootstrap/dist/css/bootstrap.min.css";

const App = () => {
  return (
    <div style={{ maxWidth: "30rem", margin: "4rem auto" }}>
      <GlobalProvider>
        <Router>
          <Routes>
            <Route exact path="/" element={<Home/>} />
            <Route path="/add" element={<AddContact/>} />
            <Route path="/edit/:id" element={<EditContact/>} />
          </Routes>
        </Router>
      </GlobalProvider>
    </div>
  )
}

export default App

Here, you can see that we have imported all our Components and used them with the help of Routes. Our program is ready. Let’s check the output in the next section to see whether all our functions work perfectly or not.

Output

To see the output, at first, we need to give the npm start command in our terminal. It will open our application on port 3000 by default. Let’s start with creating a new contact:

Here, you can see that we are in the add contact route and we write some numbers as a contact and click on the save button. It will save for us and we may see it in our home route.

We have linked the home route with the get contact list route. So, if we visit localhost:3000/ we will be able to see the created contact list.

As expected, you can see the contact list. Let’s edit it by clicking the edit button in the below section:

Here, you can see that the moment we have clicked on the Edit button it takes us to a different route that consists a Unique id. we have edited the contact with some zeros. let’s click on the edit Contact route and see what happens.

You can see that our previous contact has been updated with all zeros. Now let’s test the delete functionality in the below section:

Here, you can see that our contact has been deleted the moment we have clicked on the delete button and No contacts message has been shown as there is no contact exits.

We have successfully perform the CRUD operation in our React application. This is all about the project and by following this tutorial you may create you our CRUD application with React.

Leave a Reply

Your email address will not be published. Required fields are marked *