Storing Data Beyond a Single User Session: A Progressive Web App Solution

The Limitations of localStorage

When building a progressive web app (PWA), you may want to store information that persists beyond a single user session. This data should be accessible even when the user is offline, allowing them to continue using the app meaningfully. One might think of using Window.localStorage, a longstanding API that stores data beyond a single session. However, it presents a few key problems:

  • It’s synchronous, which can lead to performance issues.
  • It can’t be used in the context of a Worker or a ServiceWorker.
  • It only stores strings, which can be an inconvenience.

IndexedDB: A Powerful Alternative

Fortunately, there’s an alternative offline storage mechanism available in browsers called IndexedDB. It’s a transactional database system that lets you store and retrieve objects indexed with a key. Although it’s powerful, its API can be complex and overwhelming.

IDB-Keyval: A Simple Abstraction

That’s where IDB-Keyval comes in – a super-simple-small promise-based keyval store implemented with IndexedDB. Its API is essentially equivalent to localStorage, but with a few lovely differences:

  • It’s promise-based, allowing for non-blocking operations.
  • It can store anything structured-clonable, such as numbers, arrays, objects, dates, blobs, and more.

Using IDB-Keyval in a React App

Let’s demonstrate how to use IDB-Keyval in a TypeScript React app. We’ll create a simple app that enables users to choose between a dark mode and the regular display. We’ll then persist this preference using IDB-Keyval, allowing it to work both online and offline.


import { createStore } from 'idb-keyval';

const store = createStore('my-store');

function App() {
  const [theme, setTheme] = useState('light');

  useEffect(() => {
    store.set('theme', theme);
  }, [theme]);

  return (


  );
}

Implementing IDB-Keyval as a React Hook

To take it a step further, let’s create a reusable React hook called usePersistentState. This hook is modeled after the API of useState and allows us to persist state beyond page refreshes.


import { createStore } from 'idb-keyval';

const store = createStore('my-store');

function usePersistentState(key, initialState) {
  const [state, setState] = useState(initialState);

  useEffect(() => {
    store.set(key, state);
  }, [key, state]);

  useEffect(() => {
    store.get(key).then((value) => setState(value));
  }, [key]);

  return [state, setState];
}

The Benefits of Offline Storage

Offline storage leads to better user experiences. By using IDB-Keyval, we can build PWAs that provide users with a seamless experience, even when they’re offline. Whether you’re building a React, Vue, or Angular app, this solution can help you achieve offline storage with ease.

Learn more about building PWAs with offline storage.

Leave a Reply