This article is a continuation of our todo web app.
Check out part-3
Now that we have learned how to create a functional todo web app, we should move on to persist our data to the local storage using the localStorage API.
So that every time a user adds a task, the task is saved in the local storage.
Since we will need to monitor our state changes, will also use the useEffect
hook.
In App.jsx
first import useEffect
import { useState, useEffect } from 'react'
import { v4 as uniqueId } from 'uuid'
import { TrashIcon } from '@heroicons/react/24/solid'
Then add this code (above the return).
useEffect(() => {
localStorage.setItem('tasks', JSON.stringify(tasks))
}, [tasks])
Note: You could add the code anywhere as long as it is below the tasks
state and above the return
statement.
Here, the useEffect
hook monitors our tasks
state, if there is a change, the code inside the useEffect
runs.
Note: We passed tasks as our dependency array [tasks]
that's what the useEffect
will monitor.
Whenever our tasks
state changes, the local storage in the browser is updated.
First, we get access to the local storage with localStorage
then we use the setItem
method to store data in the browser's localStorage
object.
In setItem
, the first argument 'tasks'
is the key that we will use to retrieve the data later, and the second argument is the value (our actual data) of the key, which must be a string.
And because the local storage can only store string values, the second argument in setItem
must be a string, we convert tasks
array to a JSON string using JSON.stringify
, so that it can be stored as a string in localStorage
. Don't overthink too much, the whole array is just converted to one big string, simple!
We are done setting up our local storage.
Back to our app in the browser, add some tasks.
In your browser devtools, go to Application (some browsers use storage).
Then on the left side toggle(click) Local Storage. You'll see http://localhost:5173/
click it.
You should see (sometimes you'll need to click the task) π
Data stored in local storage will persist( remain there) even if you close the browser or shut down your device.
Modern smartphones and tablets have support for the localStorage
API in their web browsers.
Now that our local storage is working, we should be able to use the value stored in the local storage to update our state.
At the moment, this is what our state looks like.
const [tasks, setTasks] = useState([])
Instead of initializing our tasks to an empty array, we want to assign the data in the local storage to our tasks
.
const [tasks, setTasks] = useState(
JSON.parse(localStorage.getItem('tasks'))
)
Remember the key we set when storing data in the local storage?
Now using the method getItem
we pass the key 'tasks'
. The local storage could be holding other data. That's why we use the key to get specific info from the local storage API. The key itself is not returned, it is used as an identifier.
In the local storage, our data was stored as a string array of objects.
We used JSON.parse
to convert the string array
back to an array
that we can now iterate over in our app.
Let's go back to the browser and try reloading the application.
The tasks should persist.
Bonusπ°π°
In case you are building an app and you don't want to have errors when getting data from the local storage because of maybe the data being null
or undefined
.
You can set a default value.
Our app will still work even if you don't set a default value. This is because earlier in handleSubmit
, we made sure an empty task can not be used to update the state.
Now, this is how you set a default value.
const [tasks, setTasks] = useState(
JSON.parse(localStorage.getItem('tasks')) ?? []
)
Here, if the parsing operation fails (i.e., the retrieved value is not valid JSON), or if the parsed value is null
or undefined
, the default value will be an empty array []
The nullish coalescing operator ??
is a logical operator in JavaScript that is used to provide a default value when a variable is null
or undefined
Finally. The client side of our web app is done.
Congratulations on making it this far.πππ
Assignment: For your benefit, research the difference between JSON and json
Next up in part-5, we'll create a backend with nodejs and express the store our tasks in mongodb.