RadDevon

Using the LocalStorage API

This post is kinda long, so, if you just want to see all the code and try the app, skip down to the demo.

A Quick Overview of LocalStorage

Databases are the most common way to persist data for web applications, but they’re not always necessary. LocalStorage is a great alternative for applications that don’t need to save a ton of data, that don’t need a user’s data to follow them from computer to computer, and that don’t need users to be able to see other users’ data.

LocalStorage is a way to store simple data on a user’s machine in a way that is sandboxed. That means data is only in the browser, and each domain’s data is accessible only to applications on that same domain (e.g. google.com can’t read anything yahoo.com puts in LocalStorage).

A Simple App Using LocalStorage

I call this app “Message to the Future.” It will allow the user to enter a message and save it to LocalStorage. The next time the page is loaded, it will display the message.

The Message Form

I’ll start with a simple form to let the user enter their message:

<form action=""> <label>Message: <input type="text" name="message"></label> <button type="submit">Save</button> <span id="feedback"></span> </form> <h1 id="message"></h1>

and some very minimal styling:

#feedback { color: green; }

Here’s what it looks like:

Message to the Future UI

Saving the Message

Now, I need to make it work. I’ll start by selecting a few elements we need to interact with in our Javascript. I’m going to attach an event handler to the form so we can save the message when the user submits. I need the message text input so I can grab the text the user enters to save it. I need the feedback element to tell the user I saved their message. Finally, I need the save button because I only want a single message saved per page load; I’ll disable the button after the message is saved. Let’s capture those four elements in variables.

const messageForm = document.querySelector('form'); const messageInput = document.querySelector('[name="message"]'); const formFeedback = document.querySelector('#feedback'); const saveButton = document.querySelector('button');

Let’s write an event handler to save the message when the form is submitted. The LocalStorage API is on a global object in Javascript simply called localStorage. The two key methods we’ll be using in this app are the methods for saving and retrieving data: localStorage.setItem to save and localStorage.getItem to retrieve.

messageForm.addEventListener('submit', (event) => { event.preventDefault(); const message = messageInput.value; localStorage.setItem('message', message); formFeedback.textContent = 'Saved!'; messageInput.setAttribute('disabled', true); saveButton.setAttribute('disabled', true); });

I’m adding a listener to the message form for the 'submit' event. By hooking into 'submit' instead of the button’s 'click' event, I ensure I can run my event handler whether the user submits with the enter key or with the Save button. Then, on line 7, I have to prevent the form from sending a POST request (which is the default browser behavior when a form is submitted). Running the preventDefault method of the event takes care of that. I get the message from the message input on line 8 and save it to LocalStorage on line 9. The setItem method takes two arguments: a key (i.e. a name) for the value and the value itself. Here, I’ve named the value message and set it to the value I pulled from the message input field.

You can see the saved value in Chrome Dev Tools. Open Dev Tools from your app (by pressing Cmd-Alt-I on Mac or F11 in Windows) and go to the Application tab. You’ll find “Local Storage” in the left sidebar. Pick the domain, and you’ll see the stored message.

Our message in LocalStorage in Chrome Dev Tools

On the next three lines, I’m just giving the user some feedback. I’m displaying a “Saved!” message next to the Save button, and I’m disabling both the message field and the Save button so they know they are done interacting with the form.

Loading the Message

In the next bit of code, I’m going to select the final element I need to manipulate — the header element that will display the saved message — and I’ll load the message from LocalStorage and put it in the header.

const messageElement = document.querySelector('#message'); const message = localStorage.getItem('message'); messageElement.textContent = message;

Line 15 is where I load the message from storage. It’s important I use the same key here that I used when I saved the value or else I won’t get the saved value back. I need only pass the key into the getItem method to fetch the stored message. I set the message element’s textContent to the message, and the message is displayed on the page.

The future message on the page

Here’s the whole thing in action:

Message to the Future Demo

Once you save your message, you can see it displayed either by clicking on the “Rerun” button in the bottom left of the demo or by refreshing the whole page. https://codepen.io/raddevon/pen/QQgmvq/

When Should I Not Use LocalStorage?

Don’t use LocalStorage if your app needs any of these:

  • storage that is tied to a user rather than a computer- LocalStorage lives on the user’s computer. In fact, it lives inside the user’s browser. If your user switches from Firefox to Chrome, their data is still inside Firefox. If you change your domain name, your app won’t be able to get to the data saved on the old domain. If your user goes to a different computer, the app will not have their data.
  • more than 5MB of storage- This is the amount of storage the spec recommends browsers allocate per domain. Some older browsers allocate less. Most browsers allocate exactly this much.
  • a social element where some data is visible across users- If you want your app’s users to share anything — comments, posts, whatever — you can’t get there with LocalStorage.
  • to store complex data- LocalStorage only stores strings. You can store objects by stringifying them, but, if you need to go beyond that, you’re out of luck. For example, if you wanted to store a Javascript Date object, you’d need to store it as a string and parse that string back into a Date object. Most databases, on the other hand, have native date types and most Javascript database client libraries will automatically convert these to Date objects for you when you pull them out.
  • to search through user’s data- You could probably find a way to do searching with LocalStorage, but you’ll be much better off with a different solution.

Many apps are going to be disqualified by these limitations, but, if you can get away with using LocalStorage, you can’t beat the simplicity. It’s a great way to simply store persistent data in the browser.