Easily Save and Load User Settings

On every website I have worked on there were pieces of data that I wanted to save locally for the user, from a username that was logged in, to settings and preferences. So, for each site, I recreate (or copy and paste) the same code. For the older one it was a cookie, but now we try to avoid cookies because you have to notify the user and they are more hassle. Plus now with ubiquitous browser support of Session Storage and Local Storage (at least circa IE8 and above), I have made the switch. So then the next part is creating the boilerplate CRUD for whichever I want to use (or both). Here is a sample (the full file is here):

export function loadFromLocalStorage(valueName: string) {
    try {
        const serializedValue = localStorage.getItem(`${valueName}`);
        if (serializedValue === null || serializedValue === undefined || serializedValue === 'undefined') {
            return undefined;
        }

        return JSON.parse(serializedValue);
    } catch (err) {
        console.error(err);
        return undefined;
    }
}

export function removeFromLocalStorage(valueName: string) {
    try {
        localStorage.removeItem(`${valueName}`);
    } catch (err) {
        console.error(err);
    }
}

export function saveToLocalStorage(valueName: string, value: any) {
    try {
        const serializedState = JSON.stringify(value);
        localStorage.setItem(`${valueName}`, serializedState);
    } catch (err) {
        console.error(err);
    }
}

This time, however, when I went to do this again, I was focused on creating reusable, shareable packages and was using React. I researched packages like it and didn’t find any that would work as well and were maintained. They complicated it and were more than needed. What I ended up coming up with was different than the last times. It was code that could be easily reused, plugged into another projects, works great with vanilla JS, React, Angular, etc. It was basic and light, with no dependencies. And it works great with React. I named it simply: application-storage. I have published the source on on GitHub and published it on npm.

$ npm i application-storage

You just need three things (JavaScript example)

  1. Initialize the local or session storage class. This can be easily be done via the appStorageFactory with the second argument either “local” or “session”.
    var appStorage = appStorageFactory("nameOfPerson", "local");
  2. Save the value the user enters (appStorage.setValue())
    appStorage.setValue(name);
  3. Load the value the user entered
    var name = prompt("What is your name", appStorage.getValue());

Putting these three parts together we get a simple example prompting for a user’s name and remembering it as the default next time.

import appStorageFactory from 'application-storage';

var appStorage = appStorageFactory("nameOfPerson", "local");
var name = prompt("What is your name", appStorage.getValue());
appStorage.setValue(name);

React/Typescript Example

This next example makes saving and loading values in React effortless, which is great for components where you want to remember what the user had before, such as settings, viewing preferences or customizations (though they can’t be counted on as required persistent storage because the browser could delete them or the settings could get wiped out with a hard refresh – a database or blog storage is needed for that).

Having these types of settings saved can make the difference from frustrating a user that they always have to enter the same data, to a user who is delightfully happen that most of the time the non-mission critical settings are saved from page to page or session to session (the latter only if using local storage). Good examples of this on major websites or apps are storing the username for a user, storing what page they went to last after they logged in, or storing previous searches even if there is no logged in user.

import * as React from 'react';
import appStorageFactory from 'application-storage';

export class RememberName extends React.Component<any> {
    readonly appStorage = appStorageFactory("name", 'local');
    onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        this.appStorage.setValue(event.target.value);
        // Some event that causes a re-render
    }

    render() {
        return (
            <div>
                <label>Name: </label>
                <input value={this.appStorage.getValue()} onChange={this.onChange} />
            </div>
        );
    }
}

Again, you see the three three parts, getting an instance for your class, saving the value with an onChange event and using it as the value for the object. The gotcha is setting the value will not cause a re-render, so inside of the event you have to do something here that causes a re-render. This would normally be an update to state that tracks name, so let’s look at a more full fledged example with State.

React/Typescript with State

Here is a more realistic example with the user able to enter a form field and have it save to state, so you can act upon it in your code and do what you need with it in a normal React way, but also caching it to the storage as shown above so the user doesn’t have to enter it each time:

import * as React from 'react';
import appStorageFactory from 'application-storage';

export class RememberName extends React.Component<any, { name: string }> {
    readonly appStorage = appStorageFactory("name", 'local');

    state = {
        name: this.appStorage.getValue()
    }

    onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        this.setState({ name: event.target.value });
        this.appStorage.setValue(event.target.value);
    }

    render() {
        return (
            <div>
                <label>Name: </label>
                <input value={this.state.name} onChange={this.onChange} />
            </div>
        );
    }
}

Please let me know what you think and feel free to file any feature requests or issues on the github issues for the project. Or, if you don’t want to use the package, you can just use the code as an example of how to do the saving and loading of data. If you would like to see any other topics covered relating to saving and loading of data, feel free to put it in the comments.