localforage vs react-query vs redux-persist vs dexie-react-hooks vs use-local-storage
Web Data Storage and State Management Comparison
1 Year
localforagereact-queryredux-persistdexie-react-hooksuse-local-storageSimilar Packages:
What's Web Data Storage and State Management?

Web Data Storage and State Management libraries provide developers with tools to store, retrieve, and manage data in web applications. These libraries facilitate client-side data persistence, enabling applications to save data across sessions, synchronize state between components, and manage data efficiently. They are essential for building responsive and interactive web applications that require reliable data handling, whether for simple forms, complex state management, or offline capabilities. dexie-react-hooks is a library that provides React hooks for working with IndexedDB through Dexie.js, a wrapper around IndexedDB that simplifies its API. localforage is a library that provides a simple API for storing data in the browser using various storage backends, including IndexedDB, WebSQL, and localStorage, with a focus on asynchronous operations and improved performance. react-query is a powerful data-fetching and state management library for React applications that simplifies handling server state, caching, synchronization, and background updates, making it easier to manage remote data in a declarative way. redux-persist is a library that integrates with Redux to automatically persist and rehydrate the Redux store state across sessions, allowing for seamless state management in React applications by saving the state to localStorage or other storage engines. use-local-storage is a lightweight React hook that provides a simple interface for synchronizing state with the browser's localStorage, allowing components to read and write data to localStorage while keeping the state in sync automatically.

Package Weekly Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
localforage4,335,73425,461-2484 years agoApache-2.0
react-query1,409,01845,7492.26 MB1192 years agoMIT
redux-persist1,166,97113,010-5966 years agoMIT
dexie-react-hooks87,10213,27083.7 kB5862 years agoApache-2.0
use-local-storage30,861-19.3 kB-2 years agoMIT
Feature Comparison: localforage vs react-query vs redux-persist vs dexie-react-hooks vs use-local-storage

Data Storage Type

  • localforage:

    localforage provides a unified API for multiple storage backends, including IndexedDB, WebSQL, and localStorage. It automatically selects the best available backend based on the browser, allowing for flexible and efficient data storage without worrying about the underlying implementation.

  • react-query:

    react-query does not handle client-side data storage directly, but it manages server state by fetching data from APIs and caching it in memory. It provides features like background fetching, data synchronization, and cache invalidation, making it ideal for applications that rely on remote data sources.

  • redux-persist:

    redux-persist integrates with Redux to persist the Redux store state in a storage engine of your choice (e.g., localStorage, sessionStorage). It serializes the state and saves it, allowing for seamless rehydration of the state when the application is loaded again.

  • dexie-react-hooks:

    dexie-react-hooks uses IndexedDB, a low-level API for storing large amounts of structured data in the browser. IndexedDB is asynchronous and supports complex data types, making it suitable for applications that require efficient storage and retrieval of large datasets.

  • use-local-storage:

    use-local-storage synchronizes state with the browser's localStorage, a simple key-value storage system. It provides a straightforward way to read and write data to localStorage, making it ideal for storing small amounts of data that need to persist across sessions.

Asynchronous Support

  • localforage:

    localforage is designed for asynchronous data storage, using Promises and callbacks to handle read and write operations. This non-blocking approach ensures that the main thread remains responsive while performing storage tasks, making it suitable for applications that require smooth user interactions.

  • react-query:

    react-query excels at managing asynchronous data fetching from APIs. It provides hooks that handle Promises, manage loading and error states, and cache the results for efficient re-use. react-query simplifies the process of working with asynchronous data in React applications.

  • redux-persist:

    redux-persist handles asynchronous storage operations when saving and rehydrating the Redux state. It allows for non-blocking state persistence, which helps maintain the application's performance while managing state across sessions.

  • dexie-react-hooks:

    dexie-react-hooks provides built-in support for asynchronous operations when interacting with IndexedDB. It leverages Promises to handle data retrieval and manipulation, allowing for non-blocking operations that improve the performance of web applications.

  • use-local-storage:

    use-local-storage supports asynchronous updates to localStorage, but it primarily operates synchronously when reading and writing data. The hook updates the state and localStorage in real-time, ensuring that the data remains in sync without significant delays.

Integration with React

  • localforage:

    localforage can be used with React, but it does not provide built-in hooks. Developers can create custom hooks to integrate localforage with React components, allowing for seamless data storage and retrieval while maintaining the component's state.

  • react-query:

    react-query is specifically designed for React applications, providing hooks that integrate seamlessly with functional components. It offers a declarative approach to data fetching and state management, making it easy to handle remote data in a React-friendly way.

  • redux-persist:

    redux-persist integrates with Redux, which can be used in React applications. It automatically persists the Redux store state, allowing React components to access the persisted state without any additional setup.

  • dexie-react-hooks:

    dexie-react-hooks provides custom React hooks that simplify the integration of IndexedDB with React components. The hooks allow for easy data fetching, updating, and deletion while managing the asynchronous nature of IndexedDB operations.

  • use-local-storage:

    use-local-storage is a React hook that provides a simple interface for synchronizing state with localStorage. It can be easily integrated into React components, allowing for real-time updates to the state and localStorage.

Ease of Use: Code Examples

  • localforage:

    Using localforage for asynchronous data storage

    import localforage from 'localforage';
    
    const MyComponent = () => {
      const storeData = async () => {
        await localforage.setItem('key', 'value'); // Store data in localForage
      };
    
      const getData = async () => {
        const value = await localforage.getItem('key'); // Retrieve data from localForage
        console.log(value);
      };
    
      return (
        <div>
          <button onClick={storeData}>Store Data</button>
          <button onClick={getData}>Get Data</button>
        </div>
      );
    };
    
  • react-query:

    Using react-query for data fetching

    import { useQuery } from 'react-query';
    import axios from 'axios';
    
    const fetchData = async () => {
      const response = await axios.get('/api/data'); // Fetch data from API
      return response.data;
    };
    
    const MyComponent = () => {
      const { data, error, isLoading } = useQuery('data', fetchData);
    
      if (isLoading) return <div>Loading...</div>;
      if (error) return <div>Error: {error.message}</div>;
    
      return <div>Data: {JSON.stringify(data)}</div>;
    };
    
  • redux-persist:

    Using redux-persist to persist Redux state

    import { createStore } from 'redux';
    import { Provider } from 'react-redux';
    import { PersistGate } from 'redux-persist/integration/react';
    import { persistStore, persistReducer } from 'redux-persist';
    import storage from 'redux-persist/lib/storage'; // Default to localStorage
    
    const persistConfig = { key: 'root', storage };
    const rootReducer = (state = {}, action) => {
      switch (action.type) {
        case 'SET_DATA':
          return { ...state, data: action.payload };
        default:
          return state;
      }
    };
    
    const persistedReducer = persistReducer(persistConfig, rootReducer);
    const store = createStore(persistedReducer);
    const persistor = persistStore(store);
    
    const App = () => (
      <Provider store={store}>
        <PersistGate loading={null} persistor={persistor}>
          <MyComponent />
        </PersistGate>
      </Provider>
    );
    
  • dexie-react-hooks:

    Using dexie-react-hooks to interact with IndexedDB

    import { useDexie } from 'dexie-react-hooks';
    
    const MyComponent = () => {
      const { db } = useDexie(); // Access the Dexie database instance
    
      const addItem = async (item) => {
        await db.items.add(item); // Add an item to the IndexedDB
      };
    
      const getItems = async () => {
        return await db.items.toArray(); // Retrieve all items from IndexedDB
      };
    
      return (
        <div>
          <button onClick={() => addItem({ name: 'Item 1' })}>Add Item</button>
          <button onClick={getItems}>Get Items</button>
        </div>
      );
    };
    
  • use-local-storage:

    Using use-local-storage hook

    import { useLocalStorage } from 'use-local-storage';
    
    const MyComponent = () => {
      const [value, setValue] = useLocalStorage('myKey', 'defaultValue'); // Sync state with localStorage
    
      return (
        <div>
          <input
            type="text"
            value={value}
            onChange={(e) => setValue(e.target.value)}
          />
        </div>
      );
    };
    
How to Choose: localforage vs react-query vs redux-persist vs dexie-react-hooks vs use-local-storage
  • localforage:

    Select localforage if you want a versatile storage solution that automatically chooses the best available storage backend (IndexedDB, WebSQL, or localStorage) based on the user's browser. It is particularly useful for applications that need to store data asynchronously and handle larger amounts of data without blocking the main thread. localforage is great for projects that require a simple API for both key-value storage and more complex data structures, such as arrays and objects.

  • react-query:

    Opt for react-query if your application heavily relies on fetching, caching, and synchronizing data from remote servers or APIs. It is designed to manage server state efficiently, handle background updates, and provide a seamless experience for users by minimizing loading states and managing stale data. react-query is ideal for applications with complex data-fetching needs, such as those that require real-time updates, pagination, or infinite scrolling.

  • redux-persist:

    Choose redux-persist if you are already using Redux for state management and want to persist your Redux store state across sessions. It is particularly useful for applications that need to maintain user preferences, form data, or any other state that should be retained even after the user refreshes the page or closes the browser. redux-persist allows for easy integration with existing Redux setups and provides customizable storage options.

  • dexie-react-hooks:

    Choose dexie-react-hooks if you need a simple and efficient way to interact with IndexedDB in your React applications. It is ideal for projects that require structured data storage, offline capabilities, and support for complex queries. The library leverages Dexie.js, which provides a powerful yet easy-to-use API for working with IndexedDB, making it suitable for both beginners and experienced developers.

  • use-local-storage:

    Select use-local-storage if you need a simple and lightweight solution for synchronizing a small amount of state with the browser's localStorage. It is ideal for storing simple key-value pairs, such as user preferences or form inputs, without the overhead of a full state management solution. This hook is perfect for projects that require minimal setup and want to keep the codebase clean and straightforward.

README for localforage

localForage

Build Status NPM version Dependency Status npm jsDelivr Hits minzipped size

localForage is a fast and simple storage library for JavaScript. localForage improves the offline experience of your web app by using asynchronous storage (IndexedDB or WebSQL) with a simple, localStorage-like API.

localForage uses localStorage in browsers with no IndexedDB or WebSQL support. See the wiki for detailed compatibility info.

To use localForage, just drop a single JavaScript file into your page:

<script src="localforage/dist/localforage.js"></script>
<script>localforage.getItem('something', myCallback);</script>

Try the live example.

Download the latest localForage from GitHub, or install with npm:

npm install localforage

Support

Lost? Need help? Try the localForage API documentation. localForage API文档也有中文版。

If you're having trouble using the library, running the tests, or want to contribute to localForage, please look through the existing issues for your problem first before creating a new one. If you still need help, feel free to file an issue.

How to use localForage

Callbacks vs Promises

Because localForage uses async storage, it has an async API. It's otherwise exactly the same as the localStorage API.

localForage has a dual API that allows you to either use Node-style callbacks or Promises. If you are unsure which one is right for you, it's recommended to use Promises.

Here's an example of the Node-style callback form:

localforage.setItem('key', 'value', function (err) {
  // if err is non-null, we got an error
  localforage.getItem('key', function (err, value) {
    // if err is non-null, we got an error. otherwise, value is the value
  });
});

And the Promise form:

localforage.setItem('key', 'value').then(function () {
  return localforage.getItem('key');
}).then(function (value) {
  // we got our value
}).catch(function (err) {
  // we got an error
});

Or, use async/await:

try {
    const value = await localforage.getItem('somekey');
    // This code runs once the value has been loaded
    // from the offline store.
    console.log(value);
} catch (err) {
    // This code runs if there were any errors.
    console.log(err);
}

For more examples, please visit the API docs.

Storing Blobs, TypedArrays, and other JS objects

You can store any type in localForage; you aren't limited to strings like in localStorage. Even if localStorage is your storage backend, localForage automatically does JSON.parse() and JSON.stringify() when getting/setting values.

localForage supports storing all native JS objects that can be serialized to JSON, as well as ArrayBuffers, Blobs, and TypedArrays. Check the API docs for a full list of types supported by localForage.

All types are supported in every storage backend, though storage limits in localStorage make storing many large Blobs impossible.

Configuration

You can set database information with the config() method. Available options are driver, name, storeName, version, size, and description.

Example:

localforage.config({
    driver      : localforage.WEBSQL, // Force WebSQL; same as using setDriver()
    name        : 'myApp',
    version     : 1.0,
    size        : 4980736, // Size of database, in bytes. WebSQL-only for now.
    storeName   : 'keyvaluepairs', // Should be alphanumeric, with underscores.
    description : 'some description'
});

Note: you must call config() before you interact with your data. This means calling config() before using getItem(), setItem(), removeItem(), clear(), key(), keys() or length().

Multiple instances

You can create multiple instances of localForage that point to different stores using createInstance. All the configuration options used by config are supported.

var store = localforage.createInstance({
  name: "nameHere"
});

var otherStore = localforage.createInstance({
  name: "otherName"
});

// Setting the key on one of these doesn't affect the other.
store.setItem("key", "value");
otherStore.setItem("key", "value2");

RequireJS

You can use localForage with RequireJS:

define(['localforage'], function(localforage) {
    // As a callback:
    localforage.setItem('mykey', 'myvalue', console.log);

    // With a Promise:
    localforage.setItem('mykey', 'myvalue').then(console.log);
});

TypeScript

If you have the allowSyntheticDefaultImports compiler option set to true in your tsconfig.json (supported in TypeScript v1.8+), you should use:

import localForage from "localforage";

Otherwise you should use one of the following:

import * as localForage from "localforage";
// or, in case that the typescript version that you are using
// doesn't support ES6 style imports for UMD modules like localForage
import localForage = require("localforage");

Framework Support

If you use a framework listed, there's a localForage storage driver for the models in your framework so you can store data offline with localForage. We have drivers for the following frameworks:

If you have a driver you'd like listed, please open an issue to have it added to this list.

Custom Drivers

You can create your own driver if you want; see the defineDriver API docs.

There is a list of custom drivers on the wiki.

Working on localForage

You'll need node/npm and bower.

To work on localForage, you should start by forking it and installing its dependencies. Replace USERNAME with your GitHub username and run the following:

# Install bower globally if you don't have it:
npm install -g bower

# Replace USERNAME with your GitHub username:
git clone git@github.com:USERNAME/localForage.git
cd localForage
npm install
bower install

Omitting the bower dependencies will cause the tests to fail!

Running Tests

You need PhantomJS installed to run local tests. Run npm test (or, directly: grunt test). Your code must also pass the linter.

localForage is designed to run in the browser, so the tests explicitly require a browser environment. Local tests are run on a headless WebKit (using PhantomJS).

When you submit a pull request, tests will be run against all browsers that localForage supports on Travis CI using Sauce Labs.

Library Size

As of version 1.7.3 the payload added to your app is rather small. Served using gzip compression, localForage will add less than 10k to your total bundle size:

minified
`~29kB`
gzipped
`~8.8kB`
brotli'd
`~7.8kB`

License

This program is free software; it is distributed under an Apache License.


Copyright (c) 2013-2016 Mozilla (Contributors).