Working with the Local Storage API in JavaScript
Local Storage is a browser API that let us persist information in the browser storage, allowing us to save useful information about user preferences, such as theme, language, etc...
As you can imagine, it is a very convenient way to personalize user experience.
Due it is a browser API, you can't use it in runtimes like Node, Deno, Bun, etc.., though there are several alternatives for the server.
Main Concepts
The way Local Storage stores data is similar to an ordinary JavaScript object, that is a set of key and value pairs:
const object = {
firstKey: "hello",
secondKey: "world"
};
We can access the Local Storage data table directly in the browser DevTools:
- Open a new empty tab
- Go to the developer tools.
- Navigate to Application > Storage > Local Storage
- Select the first URL from the list
You can see something like this:
To add a new key/value pair, double click below the key column and enter a key (for example "message"). Then go to the value field and enter a value (for example "local storage").
If we reload the page, we can see that the data we've just added is still there:
Now: how can we bring this to JavaScript?
Well, it's pretty simple, but you need to know something very important first: Local Storage can only store data as a string, so we need to stringify it first.
The way JavaScript lets us do it is via the global JSON
object methods:
JSON.stringify()
accepts a valid JavaScript value (object, array, number, etc...) and returns a stringified copy:
JSON.stringify({
name: "foo",
age: 23
}); // returns "{name:"foo",age:23}"
JSON.parse()
accepts a valid stringified JavaScript value and returns its equivalent JavaScript value:
JSON.parse("{name:'foo',age:23}");
// returns {
// name: "foo",
// age: 23
// }
With this in mind, we are ready to interact with the Local Storage via JavaScript.
The Local Storage API provides us the following methods:
localStorage.setItem(<key>, <stringified-data>) // to save data
localStorage.getItem(<key>) // to get saved data by key
localStorage.key(<index>) // to get saved data by index
localStorage.removeItem(<key>) // to remove saved data by key
localStorage.clear() // to empty storage
A Real Use Case
So, let's imagine a real-world example: We need to remember the user's preferred language every time they enter the app.
For this example, i'm going to use vanila JS, but it is easily extrapolated to any library/framework.
<select name="language" id="language-select">
<option value="en">English</option>
<option value="es">Español</option>
<option value="pt">Português</option>
...
</select>
We create a select element with language options and we add it the language-select id.
// we listen for "change" events in the document
document.addEventListener("change", event => {
// we check if the event comes from our select element
if (event.target.matches("#language-select")) {
// if so, we get the selected value
const selectedLanguage = event.target.value;
// and we save it in the Local Storage
localStorage.setItem("language", selectedLanguage);
}
});
With JavaScript, we add an event listener for the entire document.
When I work with vanila JavaScript, I add only one event listener for each event I need to handle, in order to prevent event propagation and reduce the number of event listeners in the app.
Once we've added our change event listener, we check if the event target (the element that fired the event) is our select. If so, we get its value (in our example it would be en, es or pt) and save it in the Local Storage.
Note that we are not converting our value to a string because it is already a string.
Now, we can do the following:
document.addEventListener("DOMContentLoaded", () => {
const userLanguage = localStorage.getItem("language");
setLanguage(userLanguage);
// ...
});
When the page has loaded and the DOM is ready, we get the saved language from Local Storage. From here, we can use it for whatever we need.
Also, a good feature is that users can reset their language preference, and for this we would need to remove it from Local Storage:
function resetLanguage() {
localStorage.removeItem("language");
}
And, finally, in an unlikely scenario, we could completly empty the Local Storage:
localStorage.clear();
Wrapping Up
Through this tutorial, we've learned how to interact with a very useful API and its main concepts, in addition to a real use case.
If you wish to delve into topics like performance, security or best practices for this API, you can check out the articles below: