React has a vast collection of Hooks that make it easier for developers to access the props
values in various components.
In this shot, we will learn the functions of React’s useReducer
Hook.
The useReducer
Hook simply creates a store to keep track of the application state that you can then use create dispatch
method of the useReducer
Hook.
Let’s go over these concepts more clearly through code. We begin with our Sticky Notes app, which will allow users to create and delete sticky notes. On the backend, we will be using the useReducer
Hook to manage the state of the application.
First, we will start off by creating a new React app using the npx create-react-app my-react-app
command. Then, we will do the necessary clean-up and go to the App.js file, where we will declare the initial state of the app.
For this application, the initial state should have the following fields:
const initialState = {
lastNoteCreatedAt: null,
totalNotes: 0,
notes:[]
}
Here is the description of these fields:
lastNoteCreatedAt
: Displays the time when the last note was created.totalNotes
: Total number of notes to display on the header.notes
: Array of actual notes to store all of the notes.Don’t forget to import the useReducer
and useState
Hooks at the top of the App.js file. This is shown below.
import React,{useState, useReducer} from 'react'
Next, let’s create a form and a text area where the user will enter their notes.
<form className="main-form" onSubmit={addNote}>
<textarea placeholder="Add Note"
value={noteText}
onChange={(e)=>setNoteText(e.target.value)}
></textarea>
<button>Add</button>
</form>
The value attribute in the text area corresponds to the state we will need by using the useState
hook.
const [noteText, setNoteText] = useState('')
Now, let’s create our notesReducer
, where we will define what actions will take place in our app.
const notesReducer = (prevState, action) => {
switch(action.type){
case 'ADD_NOTE':
const newNote = {
lastNoteCreatedAt: new Date().toTimeString().slice(0,8),
totalNotes:prevState.notes.length +1,
notes:[...prevState.notes, action.payload]
}
// {console.log(newNote)}
return newNote;
default:
return prevState;
}
}
This notesReducer
contains an
Our reducer’s first action is the ADD_NOTE
action, which will create a new note with a time string and an array of existing notes. It also includes the newer entry and a record of total notes by adding one to the existing length of the notes array.
Now, in the app, we have to call this reducer in the manner shown below.
const [notesState, dispatch] = useReducer(notesReducer,initialState)
Our addNote()
method, called when the form is submitted, needs to do the following:
const addNote = (e) => {
e.preventDefault();
if(!noteText){
return;
}
const newNote = {
id: uuid(),
text: noteText,
rotate: Math.floor(Math.random()*20)
}
dispatch({ type:'ADD_NOTE', payload:newNote})
setNoteText('')
}
We will use the map method from Javascript to display our notes. This is shown below.
{notesState.notes.map((note)=> (
<div className="note"
key={note.id}
draggable="true"
onDragEnd={dropNote}
>
<h2 className="text">{note.text}</h2>
<button className="delete-btn" onClick={()=>deleteNote(note)}>X</button>
</div>
))}
`rotate(${note.rotate}deg)``
We have added the `` functionality in order to allow users to smoothly drag the notes to a new position. This will also require us to create the following two functions:
`draggable="true"``javascript
const dropNote = (e) => {
e.target.style.left = ``;
e.target.style.top = `${e.pageX - 50}px`;
}
const dragOver = (e) => {
e.stopPropagation();
e.preventDefault();
}
`${e.pageY - 50}px``
> This drag and drop functionality is beyond the context of this post, so I will not talk about it in much detail here, but you can find more details [here](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API).
Now, let's write the `` action, which will do the following:
* Keep the previous state intact, i.e., don't touch the existing array.
* Reduce the total number of notes by one.
* Filter the notes array and remove the one that has to be deleted.
`DELETE_NOTE``javascript
case 'DELETE_NOTE':
const deleteNote = {
...prevState,
totalNotes: prevState.notes.length -1,
notes: prevState.notes.filter(note=>note.id !== action.payload.id)
}
return deleteNote
We will call the action in a `DELETE_NOTE` function. This is called on by clicking the delete button present with each of the notes: `deleteNote
javascript
const deleteNote = (id) => {
console.log(‘delete’)
dispatch({ type:‘DELETE_NOTE’, payload: id})
}
> This brings an end to the code of our application. You can find the styling and complete code for this app [here](https://github.com/NasreenKhalid/Sticky_Notes_useReducer_React_App/tree/master).