This article will be covering React hooks, introduced in version 16.8 and the Context API, introduced in 16.3 and mixing them together to build a fully functional CRUD application. Here we won’t be using any external API calls but we’ll get our hands dirty with hard-coded objects which will serve as the state.

The introduction of the Context API solves one major problem: prop drilling. The process of getting our data from one component to another through layers of nested deep components. Whereas Hooks helps us, React developers, by allowing us to use a functional rather than class-based components. Where we needed to utilize a lifecycle method, we had to use a class-based approach. And we now no longer have to call super(props) or worry about binding methods or the this keyword.

Sometimes, the elegant implementation is just a function. Not a method. Not a class. Not a framework. Just a function.

– John Carmack. Oculus VR CTO

Less talk more code. Let’s start coding 🐊🐊🐊

As you’ll notice, we’ll be making use of Tailwind CSS for the styling of our app.

Firstly we’ll start with setting up our React project using Create React App with the following command:

$ npx create-react-app react-contextAPI

Copy

We’ll now initialize our package.json file with yarn init - and make sure we have the following dependencies below:

"react": "^16.13.0",
"react-dom": "^16.13.0",
"react-router-dom": "^5.1.2",
"react-scripts": "3.4.0",
"eslint": "^6.8.0",
"tailwindcss": "^1.2.0"

Copy

To add react-router-dom and Tailwind CSS as dependencies, just run the following command:

$ npm i react-router-dom tailwindcss

Copy

And now here are some components we’ll create in a components directory:

  • Home.js
  • AddEmployees.js
  • EditEmployees.js
  • EmployeeList.js
  • Heading.js

Import these main components inside your App component. We’ll also have to import Route and Switch from react-router-dom. And beforehand we will wrap our app with GlobalProvider which we need from GlobalState (which we’ll define later).

Here’s a quick intro to React Router if this is all new to you.

Our App.js file will look something like this:

import React from 'react';
import { Route, Switch } from 'react-router-dom';
import './stylesheet/styles.css';
import { Home } from './components/Home';
import { AddEmployee } from './components/Addemployee';
import { EditEmployee } from './components/Editemployee';

import { GlobalProvider } from './context/GlobalState';

function App() {
  return (
    <GlobalProvider>
      <Switch>
        <Route path="/" component={Home} exact />
        <Route path="/add" component={Addemployee} exact />
        <Route path="/edit/:id" component={Editemployee} exact />
      </Switch>
    </GlobalProvider>
  );
}

export default App;

Copy

We will now move forward with printing the list of Employees inside our EmployeeList.js file. The classNames that you’ll notice are Tailwind CSS utility classes and they help style our app.

EmployeeList.js

import React, { Fragment, useContext } from "react";
import { GlobalContext } from "../context/GlobalState";
import { Link } from "react-router-dom";

export const Employeelist = () => {
  const { employees, removeEmployee, editEmployee } = useContext(GlobalContext);
  return (
    <Fragment>
      {employees.length > 0 ? (
        <Fragment>
          {employees.map(employee => (
            <div
              className="flex items-center bg-gray-100 mb-10 shadow"
              key={employee.id}
            >
              <div className="flex-auto text-left px-4 py-2 m-2">
                <p className="text-gray-900 leading-none">{employee.name}</p>
                <p className="text-gray-600">{employee.designation}</p>
                <span className="inline-block text-sm font-semibold mt-1">
                  {employee.location}
                </span>
              </div>
              <div className="flex-auto text-right px-4 py-2 m-2">
                <Link to={`/edit/${employee.id}`}>
                  <button
                    onClick={() => editEmployee(employee.id)}
                    className="bg-gray-300 hover:bg-gray-400 text-gray-800 font-semibold mr-3 py-2 px-4 rounded-full inline-flex items-center"
                  >
                    <svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      strokeWidth="2"
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      className="feather feather-edit"
                    >
                      <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
                      <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
                    </svg>
                  </button>
                </Link>
                <button
                  onClick={() => removeEmployee(employee.id)}
                  className="block bg-gray-300 hover:bg-gray-400 text-gray-800 font-semibold py-2 px-4 rounded-full inline-flex items-center"
                >
                  <svg
                    xmlns="http://www.w3.org/2000/svg"
                    width="24"
                    height="24"
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    strokeWidth="2"
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    className="feather feather-trash-2"
                  >
                    <polyline points="3 6 5 6 21 6"></polyline>
                    <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
                    <line x1="10" y1="11" x2="10" y2="17"></line>
                    <line x1="14" y1="11" x2="14" y2="17"></line>
                  </svg>
                </button>
              </div>
            </div>
          ))}
        </Fragment>
      ) : (
        <p className="text-center bg-gray-100 text-gray-500 py-5">No data</p>
      )}
    </Fragment>
  );
};

Copy

In the above code we imported GlobalState and useContext, one of the built-in React Hooks, giving functional components easy access to our context.

Moreover, we imported our employees object, removeEmployee and editEmployees from our GlobalState.js file.

#react

Building a CRUD App with React Hooks &amp; the Context API
2.90 GEEK