React Hooks are a new feature added with React 16.8. It lets us use state and other class-based component features without using Class.
What are Hooks?
React Hooks are functions that allow us to hook into React state and class-based component features from function component.
Function-based component example
const Example = () => {
return <div>Function base component example</div>
}
Class-based component example
class Example extends Component {
render() {
return <div>I'm a class component</div>
}
}
In this article, I am going to create a sample application to create CRUD(Create, Read, Update, Delete) application with React Hooks. I have already posted an article to create CRUD app with class based components(without hooks), You can find here CRUD Application in React Example and Tutorial
State Hook Example
Hooks added the capability to use state with functional based components, Before hooks functional based component was stateless. See the example below to under how to declare and update the value inside the state variable with the functional component.
import React, { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
Effect Hook Example
It enables the functional component to use React life cycle methods like class-based component. See the example below:
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
Let's Get Started
At first, we will create a basic react app using create-react-app tool. Run below command on terminal/command prompt to do the same.
npx create-react-app react-hooks-crud-app
Once the above command runs successfully. You can run it with npm start and check it over browser after typing http://localhost:3000.
Create Listing View
Bootstrap CSS framework will be used to add the CDN URL to the index.html file. Here CRUD operation will be performed over list of documents which will have fields title, description, publisher. We will use here dummy records. Open app.js file inside src folder and put below code in it.
import React, { useState } from 'react';
import './App.css';
import DocumentList from './components/DocumentList'
const App= () => {
const documentData = [
{ id: 1, docTitle: 'document1', description: 'desc1', publisher: 'publisher1' },
{ id: 2, docTitle: 'document2', description: 'desc2', publisher: 'publisher2'},
{ id: 3, docTitle: 'document3', description: 'desc3', publisher: 'publisher3' },
]
// saving value to state
const [documents, setDocuments] = useState(documentData)
return (
<div className="container">
<h2 className="text-center">React.js CRUD App using Hooks</h2>
<div className="row">
<h3 className="text-center">Document List</h3>
<div className="col-md-6 col-md-offset-3">
<DocumentList documents={documents}/>
</div>
</div>
</div>
);
}
export default App;
In the above code, Below tasks have been done
- List of documents created with dummy data
- Value save saved to the state
- Inside template part(inside return)
- document list passed to a child component named DocumentList
Create DocumentList component
Create a new folder named components, and create a component file name DocumentList.js and put below code inside the fle.
import React from 'react';
const DocumentList = props =>(
<div className="table-responsive">
<table className="table">
<thead>
<tr>
<th>Title</th>
<th>Description</th>
<th>Publisher</th>
</tr>
</thead>
<tbody>
{props.documents.length > 0 ? (
props.documents.map(item => (
<tr key={item.id}>
<td>{item.docTitle}</td>
<td>{item.description}</td>
<td>{item.publisher}</td>
</tr>
))
) : (
<tr>
<td colSpan={4}>No any document available</td>
</tr>
)}
</tbody>
</table>
</div>
)
export default DocumentList
Document list data passed from parent component received through props and inside table it is rendered.
Now if you run the app on the terminal and check the app on the browser, It will look like below
Create Document task
Create a new component named AddDocument inside the components folder and put below code inside it.
import React, { useState } from 'react'
const AddDocument = props => {
const initialFormState = { id: null, docTitle: '', description: '', publisher:'' }
const [document, setDocument] = useState(initialFormState)
const handleInputChange = event => {
const { name, value } = event.target
setDocument({ ...document, [name]: value })
}
return (
<form onSubmit={event => {
event.preventDefault()
if (!document.docTitle || !document.description || !document.publisher) return
props.addDocument(document)
setDocument(initialFormState)
}}>
<input type="text" name="docTitle" placeholder="Enter Title" value={document.docTitle} onChange={handleInputChange} />
<input type="text" name="description" placeholder="Enter Description" value={document.description} onChange={handleInputChange} />
<input type="text" name="publisher" placeholder="Enter Publisher" value={document.name} onChange={handleInputChange}/>
<button className="btn btn-primary">Add Document</button>
</form>
)
}
export default AddDocument
Update App.js
Add the below line on the top of the App.js file.
import AddDocument from './components/AddDocument';
Add code below state variable initialization.
// Add Document...
const addDocument = document => {
document.id = documents.length + 1
setDocuments([...documents, document])
}
Add view part to the App component
<div>
<h3 className="text-center">Add Document</h3>
<div className="col-md-8 col-md-offset-2">
<AddDocument addDocument={addDocument} />
</div>
</div>
Now if you run the app and check it over browser, The app will look like below
Now if the new document will be added through the form, It will update the state which is having 3 lists in it.
Update & Delete Task
Update App.js file for performing update end delete task. Below is the final App.js file with methods to perform add, list, edit and delete document tasks.
import React, { useState } from 'react';
import './App.css';
import DocumentList from './components/DocumentList'
import AddDocument from './components/AddDocument';
import EditDocument from './components/EditDocument';
const App= () => {
const documentData = [
{ id: 1, docTitle: 'document1', description: 'desc1', publisher: 'publisher1' },
{ id: 2, docTitle: 'document2', description: 'desc2', publisher: 'publisher2'},
{ id: 3, docTitle: 'document3', description: 'desc3', publisher: 'publisher3' },
]
const initialFormState = { id: null, docTitle: '', description: '', publisher: '' }
const [documents, setDocuments] = useState(documentData)
const [editing, setEditing] = useState(false);
const [currentDocument, setCurrentDocument] = useState(initialFormState)
// Add Document...
const addDocument = document => {
document.id = documents.length + 1
setDocuments([...documents, document])
}
// delete documents...
const deleteDocument = id => {
setDocuments(documents.filter(document => document.id !== id))
}
// set value for edit document form...
const editDocument = document => {
setEditing(true)
setCurrentDocument({
id: document.id,
docTitle: document.docTitle,
description: document.description,
publisher : document.publisher
})
}
// update document
const updateDocument = (id, updatedDocument) => {
setEditing(false)
console.log(id,'iddddd')
setDocuments(documents.map(item => (item.id === id ? updatedDocument : item)))
}
return (
<div className="container">
<h2 className="text-center">React.js CRUD App using Hooks</h2>
<div className="row">
{editing ? (
<div>
<h2 className="text-center">Edit Document</h2>
<div className="col-md-8 col-md-offset-2">
<EditDocument
editing={editing}
setEditing={setEditing}
currentDocument={currentDocument}
updateDocument={updateDocument}
/>
</div>
</div>
) : (
<div>
<h3 className="text-center">Add Document</h3>
<div className="col-md-8 col-md-offset-2">
<AddDocument addDocument={addDocument} />
</div>
</div>
)}
</div>
<div className="row">
<h3 className="text-center">Document List</h3>
<div className="col-md-6 col-md-offset-3">
<DocumentList documents={documents} editDocument={editDocument} deleteDocument={deleteDocument}/>
</div>
</div>
</div>
);
}
export default App;
Add edit and delete button in the DocumentList component file.
<thead>
<tr>
<th>Title</th>
<th>Description</th>
<th>Publisher</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{props.documents.length > 0 ? (
props.documents.map(item => (
<tr key={item.id}>
<td>{item.docTitle}</td>
<td>{item.description}</td>
<td>{item.publisher}</td>
<td>
<button onClick={() => { props.editDocument(item) }} className="btn btn-default">Edit</button>
<button onClick={() => props.deleteDocument(item.id)} className="btn btn-default">Delete</button>
</td>
</tr>
))
) : (
<tr>
<td colSpan={4}>No any document available</td>
</tr>
)}
</tbody>
</table>
Create a new component EditDocument inside the components folder and put below code inside it.
import React, { useState, useEffect } from 'react'
const EditDocument = props => {
const [document, setDocument] = useState(props.currentDocument)
useEffect(
() => {
setDocument(props.currentDocument)
},
[ props ]
)
const handleInputChange = event => {
const { name, value } = event.target
setDocument({ ...document, [name]: value })
}
return (
<form onSubmit={event => {
event.preventDefault()
if (!document.docTitle || !document.description || !document.publisher) return
props.updateDocument(document.id, document)
}}>
<input type="text" name="docTitle" placeholder="Enter Title" value={document.docTitle} onChange={handleInputChange} />
<input type="text" name="description" placeholder="Enter Description" value={document.description} onChange={handleInputChange} />
<input type="text" name="publisher" placeholder="Enter Publisher" value={document.publisher} onChange={handleInputChange}/>
<button className="btn btn-primary">Edit Document</button>
<button onClick={() => props.setEditing(false)} className="btn btn-info">
Cancel
</button>
</form>
)
}
export default EditDocument
The above component receives the current document through props and sets it to edit form.
If you want to use API for fetching data and update, delete to the database then install Axios within the project and use it inside the different methods(add, edit, list, delete) available to get the data and update it to the database only
Run the app
Now run the app with npm start and check the app on the browser. It should perform the CRUD operation perfectly. If getting any error then download the working source code from the below download option.
Conclusion
So in this article, We learn to create CRUD applications in React.js using Hooks step by step with the easiest approach. If you want to learn more about React Hooks click here You can also find other demos of React.js Sample Projects here to start working on enterprise-level applications.
That’s all for now. Thank you for reading and I hope this demo will be very helpful for understanding the basics of React with Hooks.
Let me know your thoughts over email demo.jsonworld@gmail.com. I would love to hear them and If you like this article, share it with your friends.
Thank you!