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:
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 className
s 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