Local Storage in JavaScript
In the browser, you can access local storage through the window.localStorage
property. The window
is assumed though, so you can omit it and simply write localStorage
.
Local storage gives access to 4 important functions:
setItem(key, value)
- assign a string value to a key in local storage.getItem(key)
- get the value assigned to a key.removeItem(key)
- removes the value by key.clear()
- removes all values in local storage.
Here's the usage example:
What is local storage?
Local storage is basically a simple key-value map in your browser. It has a simple synchronous API that's available in all modern browsers.
The local storage is separate for every origin (hostname and port): https://vistontea.com
and https://blog.vistontea.com
won't share local storage.
You can inspect values stored in local storage via developer tools. For instance, using CTRL+SHIFT+C
keyboard shortcut in Chrome (or CMD+SHIFT+C
on Mac), then opening the Application tab.
Local Storage in React
In React, you can use local storage directly using plain JavaScript.
A common use case for local storage is to persist local component state. In that case, it's useful to write a custom hook that synchronizes component state to local storage.
Here's a custom useStoredState
hook example 👇
- The hook keeps the same return type as
useState
- a tuple with the value and value setter. Its parameters are the local storage key and the default value or the initializer function. - It initializes the local component state by getting its value by
key
from local storage and parsing it in the state initializer function. - A custom state setter function wraps the native
setState
with additional logic to store the value in local storage usinglocalStorage.setItem
function.
Here's how you might use it:
import * as React from 'react';
import useStoredState from './useStoredState';
export default function App() {
// 👇 Will be stored in local storage, but used as regular state
const [items, setItems] = useStoredState('items', ['item1', 'item2']);
const handleAddClick = () => {
setItems((items) => [...items, `item${items.length + 1}`]);
};
return (
<div>
<ul>
{items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
<button onClick={handleAddClick}>Add</button>
</div>
);
}
You can see the full code example with demo here: https://stackblitz.com/edit/react-ts-x4nwoj?file=App.tsx
This is how it looks like in action 👇
Using Local Storage in TypeScript
You will notice that the localStorage
property doesn't have great typings. It's useful to create your own wrapper around local storage that handles automatic value serialization and parsing.
Here's an example 👇
You could now use the storage
utility instead of localStorage
and provide the type for the value stored in local storage:
// No need to parse the value, it's handled by the wrapper
const value = storage.get<{ name: string, surname: string }>('userInfo');
Conclusion
Local storage is the easiest way to persist value in the browser, often eliminating the need for the backend server in the case of frontend-only apps.
In JavaScript, it's as simple as using functions exposed by localStorage
object. In React you may use the same API, however, it's helpful to be more declarative and create higher-level utilities. I've given an example of a custom hook that synchronizes component state to local storage.