JavaScript Tutorial: How to Use Local Storage

JavaScript Local Storage and how to manage memory on the client within the browser

Share This Post

Local Storage is a key feature that makes it possible to create a modern app with JavaScript. In fact, it is thanks to local storage that we can create the feeling of a solid and reliable app. It allows us to store data on the user’s PC and retrieve it later, even if the user closes the app or the browser. In this tutorial, we will see how to use it and why it is important.

Just a note before we start: this tutorial is all about local storage. Hence, you should already grasp the basics of JS. If you don’t, you may read our Getting Started with JavaScript tutorial first.

What is Local Storage in JavaScript?

In simple terms, Local Storage is a place where you can store dynamic information on the user’s PC. We are not talking about javascript files or other static assets, but instead about user-generated content.

In fact, a “normal” website without local storage can only save information on the server. It means that whenever you want to save, you will have to send some information to the server. For example, imagine you have an app to write blog posts. The user will edit the post in the browser, and when you are ready to save you will have to use JavaScript (or simply a form) to send the new post to the server.

The traditional approach works pretty well in most cases, but it has one significant limitation. Your application will not work if there is no network connection. Even if nowadays network connection is ubiquitous, we all know how frustrating it can be if we lose the connection even for a few minutes. And here’s where local storage comes in.

With Local Storage, you have the possibility to save some data to the user’s PC for later retrieval. Obviously, local storage is a secure area, so your application cannot access data of other applications, and vice versa. Furthermore, it’s not a folder in the PC, and you cannot access “normal” files on the PC.

Local Storage is a place where you store strings. Each string has a name, and you can save new strings, delete existing ones, or retrieve their values. But what can we do with strings? Many things, if we JSON-encode objects.

Have you ever seen in apps like Wordpres or Gmail messages like “We lost your data, but you can check the local version”? All of that happens thanks to local storage.

How to Use Local Storage in JavaScript

The Basics of Local Storage

Using Local Storage in JavaScript is actually extremely simple. You can add items, retrieve them, or delete them. All of that happens on the window.localStorage object.

To start, you will want to save some data in the local storage. The setItem() function serves that purpose. It wants to know the name of the data we want to store, and its actual value. The name is crucial, it tells what we are saving so that later we can retrieve it.

window.localStorage.setItem('postTitle', 'How to use Local Storage');

In this example, we just stored a postTitle variable. If in the future we want to read from it (i.e. “Give me the post title”) we can use the getItem() function. Obviously, since this time we are reading data and not writing, we only need to provide the name.

const title = window.localStorage.getItem('postTitle');

In case there is no post title in the local storage, this function will return undefined.

Eventually, we may want to delete something from the localStorage. As you can imagine, the removeItem() function helps us accomplish that. Just like for reading, also for removing we only need to provide a name.

window.localStorage.remoteItem('postTitle');

One note, if you use setItem() on an existing item you will override the previous value, so be careful!

While all this may seem very basic, the implications for local storage are simply massive. To see them, we need to pair it with JSON-encoded objects first.

Local Storage and JSON

You should be already familiar with objects in JavaScript (need a refresher? Here’s a tutorial). They allow you to represent complex data structures in a manageable way.

However, objects are not a string: by nature, they are more complex than that. This means we just cannot save them in local storage as they are, and that’s a shame because saving objects is what we need the most. In fact, generally, the data of our application is way more complex than simple strings – the only format local storage accepts.

Imagine we have an object that represents a post, like the one below.

const post = {
  title: 'How to use Local Storage',
  body: 'Here you have a longer piece of text ...',
  author: 'Alessandro Maggio'
};

If we were to save it to local storage one simple approach could be to save each of its properties with window.localStorage.setItem('title', 'How to use LocalStorage') and so on. We can clearly see why this is not a good approach. First, we need to interact with local storage three times for three pieces of information that are strictly related. Second, because we save them as unrelated, we may risk modifying one and not the rest.

This is not to mention more complex objects that contain arrays or that have a dynamic structure. For this, this approach quickly becomes too expensive to manage.

Fortunately for us, we can convert objects to JSON-encoded string with the JSON.stringify(object) function. This will convert the object in JSON format, a special format that maintains the description of the object.

console.log(JSON.stringify(post));
// {"title":"How to use Local Storage","body":"Here you have a longer piece of text ...","author":"Alessandro Maggio"}

We can then read those strings and load them back into an object with JSON.parse(string) method. Thus, we can go on with the following implementation.

window.localStorage.setItem('post', JSON.stringify(post));

// Later
let myPost = JSON.parse(window.localStorage.getItem('post'));

And this is it. With this simple trick, we can now save and retrieve complex objects in local storage.

Base64 to Save Files

One more thing worth mentioning is that technically we could save files into local storage. To do that, we can use a technique similar to objects, but instead of JSON-encoding, we use Base64-encoding. However, this is not recommended and against best practices. That’s because it’s slow and you store very long strings in local storage, and it wasn’t meant for that so it may not work.

Long story short, files (e.g. images, word files, and so on) are a sequence of bytes, not strings. With the base64 encoding, we can conveniently convert those sequences of bytes into string equivalents and then convert them back at a later stage.

To do this conversion, we can use atob() to create a string from files, and then btoa() to read the string and convert it back to bytes.

window.localStorage.setItem('image', atob(myBytes));
let myBytes = btoa(window.localStorage.getItem('image'));

Still, remember this is not the best practice and you should not implement that. If you are going for it, you may think twice about why you are pursuing this.

Local Storage for Full Stack Developers

This JavaScript tutorial is part of a larger free course on how to become a Full Stack Developer. Like with many things, the best way to learn is by practicing, and local storage is no exception. Thus, here you find an exercise you can try to test your knowledge and help fix those concepts in your mind.

The exercise we are doing today is related to the others we did for our Full Stack Development course, but you can tackle it even on its own. In fact, I encourage you to do so even if you are not following the course.

For the exercise, we continue building a pretend bakery website and add features to it. You can find the full code on GitHub at alessandromaggio/full-stack-course.

The Assignment

A couple of tutorials back, we created a system to dynamically add products to our cart before purchasing inside order.html. For this assignment, we are going to add a textarea on the same order.html page to allow for the user to add some notes. However, we want to keep that data saved so that in case the use reload the pages the content is not lost.

More specifically, we want to continuously save the content of the textarea to the Local Storage, every time the user modifies its content. And, of course, we want to load the content from the local storage inside the textarea as soon as we load the page. But, we want to do that only if we actually have something in the local storage.

In case you need a tip, you will need to use the input event. Even if you are not following the tutorial from the Full Stack Course, you can always create a new document with a textarea and try to save that to local storage.

Try this assignment on your own before checking out the solution below. The more you struggle toward solving the problem, the more the concept is sinking in into your mind.

The Solution

So here we go with the solution, be sure to have tried that out yourself before continue reading. In case you are interested, you can browse the solution on GitHub.com by looking at this commit.

The first thing that we have to do is add the textarea. We do that, and we give it an ID of “notes”. Additionally, we also give it a name so that the input can be processed from the backend. We decided to add it after the “Add item” button, but you can potentially add it anywhere as long as it is within the form.

<textarea name="notes" id="notes"></textarea>

Now, we can deal with the JavaScript part. Since the file that is managing the orders is script.js, we are going to add a few lines there. Here, the first thing we have to do is take care of the part that loads the stored data into the textarea.

To do that, we simply need to check if we have something saved in the local storage, and if so set it to the value of the textarea.

if (window.localStorage.getItem('notes')) {
  document.getElementById('notes').value = window.localStorage.getItem('notes');
}

Note that we are using the key notes for the local storage. That’s because this is the key we plan to use when it will become time to save, potentially any name will do as long as it is consistent.

Now, saving. This is a little more advanced but still simple enough. We need to add a listener for the input event to our textarea. To that listener, we need to provide a function that processes the event and stores the data inside the local storage. Hence, we need to accept the event object as a parameter for our function and extrapolate the text value out of that object. If we log the event (in our example e) and explore it in the console, we will see that the value we are looking for is target.value. Thus, we can write the following code.

document.getElementById('notes').addEventListener('input', function(e) {
  window.localStorage.setItem('notes', e.target.value);
});

All set! Our code is now working just fine and does what was asked.

Conclusion

Local storage is a simple yet powerful tool that enables a better user experience. Better user experience, in turn, translates into more positive reviews, better engagement, and more business for you. Something you simply cannot underlook.

With this simple tutorial on JavaScript local storage, you know know how to set up small local caches for when the connection is not available so that the user won’t lose all the content. You are all set to start diving deeper into how the frontend actually works.

Picture of Alessandro Maggio

Alessandro Maggio

Project manager, critical-thinker, passionate about networking & coding. I believe that time is the most precious resource we have, and that technology can help us not to waste it. I founded ICTShore.com with the same principle: I share what I learn so that you get value from it faster than I did.
Picture of Alessandro Maggio

Alessandro Maggio

Project manager, critical-thinker, passionate about networking & coding. I believe that time is the most precious resource we have, and that technology can help us not to waste it. I founded ICTShore.com with the same principle: I share what I learn so that you get value from it faster than I did.

Alessandro Maggio

2021-03-18T16:30:00+00:00

Unspecified

Full Stack Development Course

Unspecified