idb-keyval vs js-cookie vs localforage vs redux-persist vs store vs store2
Web Storage and State Management
idb-keyvaljs-cookielocalforageredux-persiststorestore2Similar Packages:

Web Storage and State Management

Web Storage and State Management libraries in JavaScript provide developers with tools to store data on the client side, manage application state, and persist data across sessions. These libraries leverage browser storage mechanisms like Local Storage, Session Storage, and IndexedDB to store key-value pairs, allowing for efficient data retrieval and manipulation. They help improve application performance, enable offline capabilities, and enhance user experience by retaining data between sessions. Examples include localforage, which provides a simple API for asynchronous storage across different backends, and redux-persist, which integrates with Redux to automatically persist and rehydrate application state.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
idb-keyval03,182928 kB25a year agoApache-2.0
js-cookie022,59726.2 kB33 years agoMIT
localforage025,783-2495 years agoApache-2.0
redux-persist012,971-5967 years agoMIT
store013,995-999 years agoMIT
store201,94589.4 kB5a year agoMIT

Feature Comparison: idb-keyval vs js-cookie vs localforage vs redux-persist vs store vs store2

Storage Mechanism

  • idb-keyval:

    idb-keyval uses IndexedDB as its storage mechanism, which allows for storing large amounts of structured data asynchronously. It is designed for key-value storage and provides a simple API for interacting with IndexedDB without the complexity of its native API.

  • js-cookie:

    js-cookie works with cookies, which are small pieces of data stored in the browser and sent to the server with each HTTP request. Cookies are limited in size (typically 4KB) and can have expiration dates, making them suitable for storing small amounts of data.

  • localforage:

    localforage supports multiple storage backends, including IndexedDB, WebSQL, and LocalStorage. It automatically selects the best available storage option based on the browser, allowing for efficient storage of both small and large data sets with a promise-based API.

  • redux-persist:

    redux-persist is not a storage mechanism itself but integrates with existing storage solutions (like Local Storage) to persist the Redux store state. It serializes the state and saves it to the specified storage, allowing for state rehydration on page reloads.

  • store:

    store provides a unified API for working with Local Storage, Session Storage, and Cookies. It abstracts the differences between these storage mechanisms, allowing developers to store data without worrying about which method is being used.

  • store2:

    store2 enhances the store library by adding support for namespacing, expiration, and better handling of complex data types. It also provides a unified API for Local Storage, Session Storage, and Cookies, making it easy to work with different storage methods.

Data Persistence

  • idb-keyval:

    idb-keyval provides persistent storage, meaning that data stored using the library remains available even after the browser is closed or the page is reloaded. The data is stored in IndexedDB, which is designed for long-term storage of structured data.

  • js-cookie:

    js-cookie provides temporary persistence for data stored in cookies. Cookies can have expiration dates set, allowing them to persist for a specified duration. However, they can also be deleted by the user or expire if not configured correctly.

  • localforage:

    localforage provides persistent storage across sessions by storing data in the browser using the best available backend (IndexedDB, WebSQL, or LocalStorage). The data remains available until explicitly deleted by the application or the user.

  • redux-persist:

    redux-persist provides persistence for application state by saving the Redux store data to a specified storage solution (like Local Storage). The state remains available across page reloads, making it useful for maintaining user preferences and application state.

  • store:

    store provides persistent storage for key-value pairs using Local Storage, Session Storage, or Cookies. The data remains available until it is explicitly deleted or the storage is cleared by the user or the browser.

  • store2:

    store2 provides persistent storage similar to the store library, with added features like namespacing and expiration. The data remains available until it is deleted or the storage is cleared, making it suitable for long-term storage of key-value pairs.

API Simplicity

  • idb-keyval:

    idb-keyval offers a simple and minimalistic API for interacting with IndexedDB. It provides straightforward methods for setting, getting, and deleting key-value pairs, making it easy to use without needing to understand the complexities of IndexedDB.

  • js-cookie:

    js-cookie provides a very simple and intuitive API for managing cookies. It has clear methods for setting, getting, and deleting cookies, making it easy for developers to handle cookie operations without any hassle.

  • localforage:

    localforage features a simple, promise-based API for storing and retrieving data. It abstracts the complexity of different storage backends, allowing developers to use a consistent interface for all storage operations.

  • redux-persist:

    redux-persist provides a simple API for integrating state persistence into a Redux application. It requires minimal configuration to set up and works seamlessly with existing Redux stores, making it easy to add persistence functionality.

  • store:

    store offers a straightforward API for storing and retrieving key-value pairs. It abstracts the differences between Local Storage, Session Storage, and Cookies, allowing developers to use a consistent interface for all storage operations.

  • store2:

    store2 provides a simple and intuitive API for working with Local Storage, Session Storage, and Cookies. It enhances the store library with additional features while maintaining a user-friendly interface.

Handling Complex Data

  • idb-keyval:

    idb-keyval can handle complex data types, including objects and arrays, since it stores data in IndexedDB, which supports structured data. However, the data must be serialized (e.g., using JSON) before storing and deserialized when retrieving it.

  • js-cookie:

    js-cookie is limited to handling simple data types (strings) since cookies store data as key-value pairs in string format. Complex data types must be serialized before being stored in cookies, and deserialized after retrieval.

  • localforage:

    localforage can handle complex data types natively, including objects, arrays, and binary data. It automatically serializes and deserializes data using the best available method, making it easy to store and retrieve complex data without additional processing.

  • redux-persist:

    redux-persist can handle complex data types as long as they are serializable. It serializes the entire Redux store state (including objects, arrays, and nested structures) before storing it in the specified storage solution. However, non-serializable data (e.g., functions, class instances) may require custom serialization logic.

  • store:

    store can handle complex data types, including objects and arrays, as it uses the browser's storage mechanisms (Local Storage, Session Storage, Cookies) which support stringifying data. Complex data must be serialized (e.g., using JSON.stringify) before storing and deserialized when retrieving.

  • store2:

    store2 can handle complex data types, including objects and arrays, and provides better support for them compared to the original store library. It automatically serializes and deserializes data, making it easier to work with complex structures without manual serialization.

Ease of Use: Code Examples

  • idb-keyval:

    idb-keyval Example

    import { set, get, del } from 'idb-keyval';
    
    // Set a value
    await set('key', 'value');
    
    // Get a value
    const value = await get('key');
    console.log(value);
    
    // Delete a value
    await del('key');
    
  • js-cookie:

    js-cookie Example

    import Cookies from 'js-cookie';
    
    // Set a cookie
    Cookies.set('name', 'value', { expires: 7 }); // Expires in 7 days
    
    // Get a cookie
    const value = Cookies.get('name');
    console.log(value);
    
    // Delete a cookie
    Cookies.remove('name');
    
  • localforage:

    localforage Example

    import localforage from 'localforage';
    
    // Set an item
    await localforage.setItem('key', { name: 'value' });
    
    // Get an item
    const item = await localforage.getItem('key');
    console.log(item);
    
    // Remove an item
    await localforage.removeItem('key');
    
  • redux-persist:

    redux-persist Example

    import { createStore } from 'redux';
    import { persistStore, persistReducer } from 'redux-persist';
    import storage from 'redux-persist/lib/storage'; // defaults to localStorage
    
    const persistConfig = { key: 'root', storage };
    const persistedReducer = persistReducer(persistConfig, rootReducer);
    const store = createStore(persistedReducer);
    const persistor = persistStore(store);
    
  • store:

    store Example

    import store from 'store';
    
    // Set a value
    store.set('key', 'value');
    
    // Get a value
    const value = store.get('key');
    console.log(value);
    
    // Remove a value
    store.remove('key');
    
  • store2:

    store2 Example

    import store2 from 'store2';
    
    // Set a value
    store2('namespace').set('key', 'value');
    
    // Get a value
    const value = store2('namespace').get('key');
    console.log(value);
    
    // Remove a value
    store2('namespace').remove('key');
    

How to Choose: idb-keyval vs js-cookie vs localforage vs redux-persist vs store vs store2

  • idb-keyval:

    Choose idb-keyval if you need a simple and lightweight wrapper around IndexedDB for storing key-value pairs. It is ideal for projects that require asynchronous storage with a minimal API and good performance.

  • js-cookie:

    Choose js-cookie if you need a straightforward solution for managing cookies in the browser. It provides a simple API for setting, getting, and deleting cookies, making it easy to handle cookie-based data without dealing with the complexities of the document.cookie API.

  • localforage:

    Choose localforage if you want a library that provides a simple, promise-based API for storing data in the browser using various storage backends (IndexedDB, WebSQL, and LocalStorage). It automatically selects the best available storage option, making it versatile and easy to use for both small and large data sets.

  • redux-persist:

    Choose redux-persist if you are using Redux for state management and want to automatically persist your Redux store to local storage (or other storage engines) between page reloads. It helps maintain application state across sessions with minimal configuration.

  • store:

    Choose store if you need a simple and lightweight library for storing key-value pairs in the browser. It provides a unified API for working with Local Storage, Session Storage, and Cookies, making it easy to store data across different storage mechanisms without worrying about the implementation details.

  • store2:

    Choose store2 if you want an enhanced version of the store library with support for namespacing, expiration, and better handling of complex data types. It is suitable for projects that require more advanced features while still maintaining a simple and intuitive API.

README for idb-keyval

IDB-Keyval

npm

This is a super-simple promise-based keyval store implemented with IndexedDB, originally based on async-storage by Mozilla.

It's small and tree-shakeable. If you only use get/set, the library is 295 bytes (brotli'd), if you use all methods it's 573 bytes.

localForage offers similar functionality, but supports older browsers with broken/absent IDB implementations. Because of that, it's orders of magnitude bigger (~7k).

This is only a keyval store. If you need to do more complex things like iteration & indexing, check out IDB on NPM (a little heavier at 1k). The first example in its README is how to create a keyval store.

Installing

Recommended: Via npm + webpack/rollup/parcel/etc

npm install idb-keyval

Now you can require/import idb-keyval:

import { get, set } from 'idb-keyval';

If you're targeting IE10/11, use the compat version, and import a Promise polyfill.

// Import a Promise polyfill
import 'es6-promise/auto';
import { get, set } from 'idb-keyval/dist/esm-compat';

All bundles

A well-behaved bundler should automatically pick the ES module or the CJS module depending on what it supports, but if you need to force it either way:

  • idb-keyval/dist/index.js EcmaScript module.
  • idb-keyval/dist/index.cjs CommonJS module.

Legacy builds:

  • idb-keyval/dist/compat.js EcmaScript module, transpiled for older browsers.
  • idb-keyval/dist/compat.cjs CommonJS module, transpiled for older browsers.
  • idb-keyval/dist/umd.js UMD module, also transpiled for older browsers.

These built versions are also available on jsDelivr, e.g.:

<script src="https://cdn.jsdelivr.net/npm/idb-keyval@6/dist/umd.js"></script>
<!-- Or in modern browsers: -->
<script type="module">
  import { get, set } from 'https://cdn.jsdelivr.net/npm/idb-keyval@6/+esm';
</script>

Usage

set:

import { set } from 'idb-keyval';

set('hello', 'world');

Since this is IDB-backed, you can store anything structured-clonable (numbers, arrays, objects, dates, blobs etc), although old Edge doesn't support null. Keys can be numbers, strings, Dates, (IDB also allows arrays of those values, but IE doesn't support it).

All methods return promises:

import { set } from 'idb-keyval';

set('hello', 'world')
  .then(() => console.log('It worked!'))
  .catch((err) => console.log('It failed!', err));

get:

import { get } from 'idb-keyval';

// logs: "world"
get('hello').then((val) => console.log(val));

If there is no 'hello' key, then val will be undefined.

setMany:

Set many keyval pairs at once. This is faster than calling set multiple times.

import { set, setMany } from 'idb-keyval';

// Instead of:
Promise.all([set(123, 456), set('hello', 'world')])
  .then(() => console.log('It worked!'))
  .catch((err) => console.log('It failed!', err));

// It's faster to do:
setMany([
  [123, 456],
  ['hello', 'world'],
])
  .then(() => console.log('It worked!'))
  .catch((err) => console.log('It failed!', err));

This operation is also atomic – if one of the pairs can't be added, none will be added.

getMany:

Get many keys at once. This is faster than calling get multiple times. Resolves with an array of values.

import { get, getMany } from 'idb-keyval';

// Instead of:
Promise.all([get(123), get('hello')]).then(([firstVal, secondVal]) =>
  console.log(firstVal, secondVal),
);

// It's faster to do:
getMany([123, 'hello']).then(([firstVal, secondVal]) =>
  console.log(firstVal, secondVal),
);

update:

Transforming a value (eg incrementing a number) using get and set is risky, as both get and set are async and non-atomic:

// Don't do this:
import { get, set } from 'idb-keyval';

get('counter').then((val) =>
  set('counter', (val || 0) + 1);
);

get('counter').then((val) =>
  set('counter', (val || 0) + 1);
);

With the above, both get operations will complete first, each returning undefined, then each set operation will be setting 1. You could fix the above by queuing the second get on the first set, but that isn't always feasible across multiple pieces of code. Instead:

// Instead:
import { update } from 'idb-keyval';

update('counter', (val) => (val || 0) + 1);
update('counter', (val) => (val || 0) + 1);

This will queue the updates automatically, so the first update set the counter to 1, and the second update sets it to 2.

del:

Delete a particular key from the store.

import { del } from 'idb-keyval';

del('hello');

delMany:

Delete many keys at once. This is faster than calling del multiple times.

import { del, delMany } from 'idb-keyval';

// Instead of:
Promise.all([del(123), del('hello')])
  .then(() => console.log('It worked!'))
  .catch((err) => console.log('It failed!', err));

// It's faster to do:
delMany([123, 'hello'])
  .then(() => console.log('It worked!'))
  .catch((err) => console.log('It failed!', err));

clear:

Clear all values in the store.

import { clear } from 'idb-keyval';

clear();

entries:

Get all entries in the store. Each entry is an array of [key, value].

import { entries } from 'idb-keyval';

// logs: [[123, 456], ['hello', 'world']]
entries().then((entries) => console.log(entries));

keys:

Get all keys in the store.

import { keys } from 'idb-keyval';

// logs: [123, 'hello']
keys().then((keys) => console.log(keys));

values:

Get all values in the store.

import { values } from 'idb-keyval';

// logs: [456, 'world']
values().then((values) => console.log(values));

Custom stores:

By default, the methods above use an IndexedDB database named keyval-store and an object store named keyval. If you want to use something different, see custom stores.