In this tutorial, I'll teach you how to save persistent data to the user's browser using the localStorage
object, which is part of the HTML Web Storage API. I'll cover some simple use cases, including saving a game hiscore, some to-do list data and the user's light/dark mode preference.
I first came across localStorage
when I was building a to-do list app โ I guess this is a rite of passage when you start learning front-end development! But a to-do list app is not of much use if you can't store the user's list somehow! Likewise, I'd also made some simple games where I wanted to be able to save the user's best score.
Thanks to the Web Storage API, storing persistent data in the user's browser is actually very quick, simple and reliable.
What is the Web Storage API?
The Web Storage API was introduced in HTML5 and is fully supported across all major desktop and mobile browsers. This API allows you to store data in a key-value pair format directly in the user's browser. Typically, you can store around 5MB per origin but this varies between browsers. Don't worry, I'll discuss "origin" in the next section.
The Web Storage API comprises two storage objects sessionStorage
and localStorage
. In this tutorial, I'll be focusing on localStorage
but they both work in the same way and use the same methods and properties. The key difference between the two is data persistence.
For sessionStorage
, stored data survives a page refresh but is cleared on tab or browser closure. True to its name, the data only persists for the session.
In contrast, data stored in localStorage
has no expiration date and persists across page refreshes, tab closures and browser and OS restarts. So, the data is more-or-less permanent. You can only delete this data using JavaScript, the browser dev tools or by clearing the browser cache.
It's worth mentioning that the Web Storage API is different to using cookies. For a starter, cookies can only store a measly 4kB of data. But the main difference is that Web Storage is client-side only. No data is sent server-side, you can only control it through JavaScript and the storage is bound to the origin.
So, localStorage
generally has no performance impact but if you want to send data server-side, then cookies may be a better option.
Cookies are also delicious, especially with coffee ๐ชโ
What does origin mean?
Origin kinda means website but, more specifically, it means per domain, protocol and port.
So, for example:
https://mydomain.com/home
andhttps://mydomain.com/about
have the same domain and protocol, so would share the same storage object in the user's browserhttps://mydomain.com/home
andhttp://mydomain.com/home
use different protocols, so would use separate storage objectshttps://mydomain.com/home
andhttps://anotherdomain.com/home
are on different domains, so would also use separate storage objectshttp://localhost:3000
andhttp://localhost:4000
are on different ports, so again would use separate storage objects
How to use localStorage
As I mentioned earlier, storing and retrieving data from localStorage
is quick and simple. You just call the setItem()
and getItem()
methods on the localStorage
object.
Using setItem() and getItem()
To store data in the browser, you call the setItem()
method and pass in the key (a name) and value (your data) as arguments:
localStorage.setItem('myKey', 'random value')
localStorage.setItem('fav drink', 'coffee')
You can then retrieve this data by calling the getItem()
method and passing in the name of the key you wish to access:
const myValue = localStorage.getItem('myKey')
console.log(myValue) // logs: 'random value'
const myFavDrink = localStorage.getItem('fav drink')
console.log(myFavDrink) // logs: 'coffee'
Existing keys will be overwritten, which allows you to easily update the values stored in localStorage
:
localStorage.setItem('fav drink', 'black coffee')
console.log(localStorage.getItem('fav drink')) // logs: 'black coffee'
You can also view the contents of the localStorage
object with your browser dev tools. For example, you can find it under the Application tab in Chrome and the Storage tab in Firefox.
Here is a screenshot of what localStorage
looks like in Firefox, where you can see all the key-value pairs I've created in this article:
Using object dot notation
An even simpler way to set and retrieve data is using object dot notation:
localStorage.username = 'Bobby McBobFace'
console.log(localStorage.username) // logs: 'Bobby McBobFace'
However, using object dot notation can potentially cause issues if the key name is derived from user input. Say, for example, the user provides a key name of length
, which is a built-in property of localStorage
:
localStorage.length = 'very long'
console.log(localStorage.getItem('length')) // logs: null
localStorage.setItem('length', 'very long')
console.log(localStorage.getItem('length')) // logs: 'length'
console.log(localStorage.length) // logs: 3
So, localStorage.length
is returning the number of stored items in the object!
Obviously, this also applies to other key names that clash with localStorage
properties/methods but there's not that many of them (see next section) so it's unlikely to be a problem in most cases.
Another drawback of using dot notation for storing and modifying values is that the storage
event won't fire. The storage
event allows different tabs/windows from the same origin to communicate via event listeners but I won't go into this here!
Methods and properties
Both localStorage
and sessionStorage
also have access to the following methods, which you can call using standard dot notation:
removeItem(key)
โ deletes the specified key-value pair, e.g.localStorage.removeItem('fav drink')
clear()
โ deletes all key-value pairs for the origin, so be careful!length
โ returns the number of key-value pairs (i.e. stored items) for the originkey(index)
โ returns the value for a given index, e.g.localStorage.key(3)
It's worth noting here that localStorage
and sessionStorage
are actually array-like objects as opposed to standard JavaScript objects, hence why they have indexed properties and a length
.
Strings only!
You may have spotted that all my examples so far have used strings as a value! Well, that's because both keys and values must be strings. In fact, all primitive data types will automatically be converted to a string and you will need to covert arrays and objects to a string before saving to localStorage
.
In the use case examples in the next section, I'll demonstrate how to store and retrieve several other data types.
Some simple use cases
In this section, I'll show you some simple use cases for using the Web Storage API, specifically localStorage
.
A game hiscore
If you're building a game that generates a score, then saving the user's hiscore is surely a must! localStorage
will coerce that score into a string but there are few ways to convert it back to a number:
localStorage.setItem('hiscore', 1984)
let hiscore = localStorage.getItem('hiscore')
console.log(typeof hiscore) // logs: 'string'
let hiscoreMultiply = hiscore * 1
console.log(typeof hiscoreMultiply) // logs: 'number'
Another way to convert hiscore
is to use the Number()
object:
let hiscoreNumber = Number(hiscore)
console.log(typeof hiscoreNumber) // logs: 'number'
Lastly, you can use JSON.parse()
:
let hiscoreParse = JSON.parse(hiscore)
console.log(typeof hiscoreParse) // logs: 'number'
To-do list data
For coding a to-do list app, your list of items will likely be stored as objects inside an array. To put this array into storage, it needs to be converted to a string first, which you can do using JSON.stringify()
:
let todolist = [
{id: 1, item: 'make fresh coffee', checked: true},
{id: 2, item: 'learn to code', checked: false},
{id: 3, item: 'feed Takeshi', checked: false}
]
let storeMe = JSON.stringify(todolist)
localStorage.setItem('todolist', storeMe)
When retrieving the to-do list, you'll want to convert the string back into an object:
let unStoreMe = JSON.parse(localStorage.getItem('todolist'))
Light/dark mode preference
If you're designing a webpage with a light/dark mode toggle, then it's a good idea to store the user's preference for future visits. Typically, this will mean dealing with a boolean that gets coerced into a string when put in localStorage
.
Again, JSON.parse()
comes to the rescue:
let isDarkThemeOn = true
localStorage.setItem('isDarkThemeOn', isDarkThemeOn)
console.log(typeof localStorage.getItem('isDarkThemeOn')) // logs: 'string'
isDarkThemeOn = JSON.parse(localStorage.getItem('isDarkThemeOn'))
console.log(typeof isDarkThemeOn) // logs: 'boolean'
Conclusion
Using the localStorage
object, you can quickly and easily store and retrieve data from the user's browser. This data will have no expiration data and can only be manipulated through JavaScript or the dev tools. However, it can be deleted if the user clears their browser cache.
When you add primitive data types to the localStorage
object, they will automatically be converted to strings. For arrays and objects, you will need to stringfy them before saving to localStorage
. You can convert the strings back to their original data type using JSON.parse()
.