A Custom Hook for Local Storage: `useLocalStorage` (Part 1) - Persisting State in the Browser #86
📖 Introduction
Following our exploration of the useFetch
hook, this article introduces another incredibly useful custom hook: useLocalStorage
. We will learn how to create a hook that simplifies the process of storing and retrieving data from the browser's local storage, allowing us to persist state across browser sessions.
📚 Prerequisites
Before we begin, please ensure you have a solid grasp of the following concepts:
- React Hooks, especially
useState
anduseEffect
. - The
localStorage
API. JSON.stringify()
andJSON.parse()
.
🎯 Article Outline: What You'll Master
In this article, you will learn:
- ✅ The Problem: Understanding the need to persist state and the boilerplate involved in using
localStorage
directly. - ✅ Core Implementation: How to build a
useLocalStorage
hook from scratch. - ✅ Practical Application: How to use the
useLocalStorage
hook in a component to create a persistent counter.
🧠 Section 1: The Core Concepts of a useLocalStorage
Hook
In many applications, you'll want to save some of the user's data so that it's not lost when they refresh the page or close the browser. The localStorage
API allows us to do this, but using it directly in our components can be repetitive.
A useLocalStorage
hook abstracts away the logic for interacting with localStorage
, providing a simple and reusable way to manage persistent state. It will have an API similar to useState
, but with the added benefit of automatically saving the state to localStorage
.
💻 Section 2: Deep Dive - Implementation and Walkthrough
Let's build the useLocalStorage
hook.
2.1 - The useLocalStorage
Hook
Create a new file called useLocalStorage.js
:
// useLocalStorage.js
import { useState, useEffect } from 'react';
function getStorageValue(key, defaultValue) {
const saved = localStorage.getItem(key);
const initial = JSON.parse(saved);
return initial || defaultValue;
}
function useLocalStorage(key, defaultValue) {
const [value, setValue] = useState(() => {
return getStorageValue(key, defaultValue);
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue];
}
export default useLocalStorage;
Step-by-Step Code Breakdown:
getStorageValue
: This helper function retrieves the initial value fromlocalStorage
.- It takes a
key
and adefaultValue
. - It gets the item from
localStorage
and parses it as JSON. - If no value is found, it returns the
defaultValue
.
- It takes a
useLocalStorage
: This is our custom hook.useState
: We useuseState
with a function as the initial value. This ensures that we only read fromlocalStorage
on the initial render.useEffect
: We useuseEffect
to updatelocalStorage
whenever thekey
orvalue
changes.return [value, setValue]
: We return thevalue
andsetValue
function, just likeuseState
.
🛠️ Section 3: Project-Based Example: A Persistent Counter
Now, let's use our new useLocalStorage
hook to create a counter that remembers its value even after a page refresh.
// PersistentCounter.js
import React from 'react';
import useLocalStorage from './useLocalStorage';
function PersistentCounter() {
const [count, setCount] = useLocalStorage('my-app-counter', 0);
return (
<div>
<h1>Persistent Counter</h1>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(count - 1)}>Decrement</button>
</div>
);
}
export default PersistentCounter;
Code Breakdown:
import useLocalStorage from './useLocalStorage';
: We import our custom hook.const [count, setCount] = useLocalStorage('my-app-counter', 0);
: We call ouruseLocalStorage
hook with a key and a default value.- We then use the
count
andsetCount
variables just like we would with a regularuseState
hook.
Now, if you increment or decrement the counter and then refresh the page, the count will be preserved.
💡 Conclusion & Key Takeaways
Congratulations! You've created a powerful useLocalStorage
hook that simplifies the process of persisting state in your React applications.
Let's summarize the key takeaways:
- The
useLocalStorage
hook provides a simple and reusable way to manage persistent state. - It has an API that is similar to
useState
, making it easy to use. - By creating a
useLocalStorage
hook, you can make your state management logic more consistent and easier to maintain.
Challenge Yourself:
To solidify your understanding, try to create a simple theme switcher component that uses the useLocalStorage
hook to persist the selected theme.
➡️ Next Steps
You now have a solid understanding of how to create a useLocalStorage
hook. In the next article, "A Custom Hook for Local Storage: useLocalStorage
(Part 2)", we will explore how to handle objects and arrays in local storage and how to sync state between different tabs.
Thank you for your dedication. Stay curious, and happy coding!
glossary
useLocalStorage
: A custom hook for persisting state in the browser's local storage.localStorage
: A web storage API that allows you to store key-value pairs in a web browser with no expiration date.JSON.stringify()
: A JavaScript method that converts a JavaScript object or value to a JSON string.JSON.parse()
: A JavaScript method that parses a JSON string, constructing the JavaScript value or object described by the string.