JSPM

  • Created
  • Published
  • Downloads 3013
  • Score
    100M100P100Q109960F
  • License MIT

Persistence layer for redux with flexible backends

Package Exports

  • redux-storage

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (redux-storage) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

redux-storage

license npm version npm downloads Code Climate

Save and load the Redux state with ease.

Features

  • Flexible storage engines
  • Storage engines can be async
  • Load and save actions that can be observed
    • SAVE: { type: 'REDUX_STORAGE_SAVE', payload: /* state tree */ }
    • LOAD: { type: 'REDUX_STORAGE_LOAD', payload: /* state tree */ }
  • Various engine decorators
  • Blacklist actions from issuing a save operation

Installation

npm install --save redux-storage

Usage

// Import redux and all your reducers as usual
import { createStore, applyMiddleware, combineReducers } from 'redux';
import * as reducers from './reducers';

// We need to wrap the base reducer, as this is the place where the loaded
// state will be injected.
//
// Note: The reducer does nothing special! It just listens for the LOAD
//       action and merge in the provided state :)
const reducer = storage.reducer(combineReducers(reducers));

// Now it's time to decide which storage engine should be used
//
// Note: The arguments to `createEngine` are different for every engine!
import createEngine from 'redux-storage/engines/reactNativeAsyncStorage';
const engine = createEngine('my-save-key');

// And with the engine we can create our middleware function. The middleware
// is responsible for calling `engine.save` with the current state afer
// every dispatched action.
//
// Note: You can provide a list of action types as second argument, those
//       actions will be filtered and WON'T trigger calls to `engine.save`!
const middleware = storage.createMiddleware(engine);

// As everything is prepared, we can go ahead and combine all parts as usual
const createStoreWithMiddleware = applyMiddleware(middleware)(createStore);
const store = createStoreWithMiddleware(reducer);

// At this stage the whole system is in place and every action will trigger
// a save operation.
//
// BUT (!) a existing old state HAS NOT been restored yet! It's up to you to
// decide when this should happen. Most of the times you can/should do this
// right after the store object has been created.

// To load the previous state we create a loader function with our prepared
// engine. The result is a function that can be used on any store object you
// have at hand :)
const load = storage.createLoader(engine);
load(store);

Details

Engines

reactNativeAsyncStorage

This will use AsyncStorage out of react-native.

import createEngine from 'redux-storage/engines/reactNativeAsyncStorage';
const engine = createEngine('my-save-key');

Warning: react-native is not a dependency of redux-storage! You have to install it separately.

localStorage

Stores everything inside window.localStorage.

import createEngine from 'redux-storage/engines/localStorage';
const engine = createEngine('my-save-key');

Warning: localStorage does not expose a async API and every save/load operation will block the JS thread!

Actions

redux-storage will trigger actions after every load or save operation from the underlying engine.

You can use this, for example, to display a loading screen until the old state has been restored like this:

import { LOAD, SAVE } from 'redux-storage';

function storeageAwareReducer(state = { loaded: false }, action) {
    switch (action.type) {
        case LOAD:
            return { ...state, loaded: true };

        case SAVE:
            console.log('Something has changed and written to disk!');

        default:
            return state;
    }
}

Middleware

If you pass an array of action types as second argument to createMiddleware, those will be added to a internal blacklist and won't trigger calls to engine.save.

import storage from 'redux-storage'

import { APP_START } from './constants';

const middleware = storage.createMiddleware(engine, [ APP_START ]);

Decorators

Decorators simply wrap your engine instance and modify/enhance it's behaviour.

Filter

Use this decorator to write only part of your state tree to disk.

import storage from 'redux-storage'

engine = storage.decorators.filter(engine, [
    ['some', 'key'],
    ['another', 'very', 'nested', 'key']
]);

Debounce

This decorator will delay the expensive save operation for the given ms. Every new change to the state tree will reset the timeout!

import storage from 'redux-storage'

engine = storage.decorators.debounce(engine, 1500);

Immutablejs

Convert parts of the state tree into Immutable objects on engine.load.

import storage from 'redux-storage'

engine = storage.decorators.immutablejs(engine, [
    ['immutablejs-reducer'],
    ['plain-object-reducer', 'with-immutablejs-key']
]);

Todo

  • Write tests for everything!