Local Storage In JavaScript / HTML5 Tutorial
SaaS providers have gotten really good at letting you use their applications despite the constant loss of Internet connectivity as you move to and fro with your mobile device. This seamless experience wouldn’t be possible without the use of some kind of client side storage. In the proceeding post, I’ll attempt to give a high level overview of the different forms of persistent storage on browsers.
Cookies
When receiving an HTTP request, a server can send a Set-Cookie
header with the response. The cookie is usually stored by the browser, and then the cookie is sent with each subsequent request made to the same server. An expiration date or duration can be specified, after which the cookie is no longer sent.
Cookies are mainly used by servers to distinguish one user from the hundreds or thousands of users making requests at any given point in time. There are three main reasons why we’d want to know what user is making what kind of request.
- **Session management — **Logins, shopping carts, game scores or anything else the server should remember
- **Personalization — **User preferences, themes or other settings
- **Tracking — **Recording and analyzing user behaviour
Cookies generally have a maximum size of around 4 KB, which is not much good for storing any kind of complex data. With HTML5, you have several choices for storing your data, depending on what you want to store. The storage limits depend on what system your browser is running on (desktop vs mobile) and what you’re using to store your data (localStorage vs indexedDB).
Session Storage
Session storage is relatively easy to work with. You can access and mutate key/value pairs using a simple javascript API. For example:
sessionStorage['name'] = 'Cory';
You can view the contents of the session storage at any time by opening up the DevTools and navigating to the application tab.
To retrieve that data from storage, you simply pass the key as an argument.
alert(sessionStorage['name']);
If we were to try closing and reopening the tab, the data in session storage would be gone.
Local Storage
LocalStorage is similar to sessionStorage, except that data stored in localStorage doesn’t get cleared when the browsing session ends (i.e. when the window or tab is closed).
The interface for localStorage is the same as sessionStorage, for example:
localStorage['cat'] = 'Rose';
To retrieve that data from storage, you simply pass the key as an argument.
alert(localStorage['cat']);
The data persists after closing and reopening the tab.
In browsers like FireFox and Chrome, localStorage is deleted when the user manually clears their browsing history or cookies and other side data.
IndexedDB
You could obviously use localStorage for simple requirements but IndexedDB has a larger storage capacity and scales better.
IndexedDB is particularly useful if you want a client that can be used without an internet connection. For example Google Docs allows users to work offline and synchronizes their changes when the network becomes available again.
Another use case is to store redundant and seldom modified but often accessed data in the IndexedDB to avoid having to fetch it from the server. It adds too much latency to make a HTTP request every time you want to access the data. In addition, making frequent requests for data that is unlikely to have changed on the server side would place unnecessary strain on the database.
I don’t actually recommend interacting with the IndexedDB interface directly. There a numerous npm packages (i.e. localforage) that wrap the functionality in a promise based API. For those of you who want to learn more about how it works under the hood, here’s a link to the documentation on MDN.
IndexedDB API
_IndexedDB is a low-level API for client-side storage of significant amounts of structured data, including files/blobs…_developer.mozilla.org
In the proceeding section we’ll walkthrough a basic example of how to store and retrieve data using IndexedDB. We’ll use create-react-app
for our boilerplate.
npx create-react-app indexeddb-example
Once inside the repository, install localforage
using either yarn or npm.
yarn add localforage
We can store and retrieve key/value pairs using the following code.
import React, { Component } from 'react';
import { default as localforage } from 'localforage';
class App extends Component {
constructor(props) {
super(props);
this.p = null;
this.state = {
value: ''
};
this.handleOnClick = this.handleOnClick.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
render() {
return (
Favorite Color
Retrieve data
this.p = elem }>
);
}
handleChange (e) {
this.setState({value: e.target.value});
}
handleOnClick () {
localforage.getItem('somekey').then(value => {
// This code runs once the value has been loaded from the offline store.
this.p.innerText = value;
}).catch(err => {
// This code runs if there were any errors
console.log(err);
});
}
handleSubmit (e) {
e.preventDefault();
localforage.setItem('somekey', this.state.value).then(value => {
// Do other things once the value has been saved.
}).catch(err => {
// This code runs if there were any errors
console.log(err);
});
}
}
export default App;
It’s also possible to store and retrieve images in the form of blobs.
import React, { Component } from 'react';
import { default as localforage } from 'localforage';
class App extends Component {
constructor(props) {
super(props);
this.p = null;
this.img = null;
this.state = {
value: ''
};
this.handleOnClick = this.handleOnClick.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
this.retrieveCatImage = this.retrieveCatImage.bind(this);
this.storeCatImage = this.storeCatImage.bind(this);
}
render() {
return (
Favorite Color
Retrieve data
store cat image
Retrieve cat image
this.p = elem }>
this.img = elem } />
);
}
handleChange (e) {
this.setState({value: e.target.value});
}
handleOnClick () {
localforage.getItem('somekey').then(value => {
// This code runs once the value has been loaded from the offline store.
this.p.innerText = value;
}).catch(err => {
// This code runs if there were any errors
console.log(err);
});
}
handleSubmit (e) {
e.preventDefault();
localforage.setItem('somekey', this.state.value).then(value => {
// Do other things once the value has been saved.
}).catch(err => {
// This code runs if there were any errors
console.log(err);
});
}
storeCatImage () {
fetch('http://localhost:5000/cat.png').then(response => {
response.blob().then(image => {
localforage.setItem('photo', image).then(value => {
// Do other things once the value has been saved.
});
});
});
}
retrieveCatImage () {
localforage.getItem('photo').then(value => {
// This code runs once the value has been loaded from the offline store.
var blob = new Blob([value]);
var imageURI = window.URL.createObjectURL(blob);
// this.img.src = imageURI;
document.querySelector('img').src = imageURI;
}).catch(err => {
// This code runs if there were any errors
console.log(err);
});
}
}
export default App;
You can find the source code here.
Cory Maklin
_Sign in now to see your channels and recommendations!_www.youtube.com