npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@actra-development-oss/redux-persistable

v3.0.0

Published

State persistance for redux stores

Downloads

77

Readme

redux-persistable

State persistance for redux stores supporting immutable.js, lazy reducers, versioned states, migrations and merged storage

Features

  • Supports immutable.js for the whole state
  • Supports lazily added reducers by storing the slices of state in separate storage keys
    • Hooks into redux' replaceReducer() to catch up with new reducer map
    • Dispatches rehydrate actions for every slice for reducers to implement custom rehydration logic
    • Dispatches rehydrated actions for every slice to inform the app that a new slice has been loaded and rehydrated
  • ActionBuffer while rehydrating
    • Hooks into redux' dispatch() to buffer dispatched actions while rehydration is in progress
    • Flushes action buffer in FIFO order after rehydration finished
  • Versioned states, versions are persisted with the state slices but not published to the state upon loading to not clutter it with internals
  • Migrations from old state versions to latest by specifying migration functions
    • Migrations are processed in serial order so there's no need to bloat them with steps for all possible previous versions
      • Input version: 2
      • Migration versions: 2, 3, 4, 5
      • redux-persistable will pass the de-serialized data to migration "3", the result of this to "4" and that to "5"
    • Migration functions can process multiple version steps at once, they have to return the version the migrated state is in
      • Input version: 2
      • Migration versions: 2, 5, 10
      • redux-persistable will pass input to migration "5" which handles migrations from 2 to 5 and will pass the result to "10" which handles migration from 5 to 10
  • Multiple storages available: LocalForage, native LocalStorage, native SessionStorage, MergedStorage
    • Custom storages can be implemented, see AbstractStorage for e.g. version handling
    • MergedStorage: store slices of the state to different storages (e.g. LocalStorage and SessionStorage) and automatically merge them upon loading
    • Custom serializers possible, ships with simple serializer (JSON.stringify / JSON.parse) and immutable serializer (remotdev-serialize / jsan)

Usage

import {
    combineReducers,
    immutableMerger,
    ImmutableSerializer,
    LocalstorageStorage,
    MergerType,
    persistableEnhancer,
    SerializerType,
    TransformType
} from '@actra-development-oss/redux-persistable/lib';
import {
    Map,
    Record
} from 'immutable';
import {
    Action,
    applyMiddleware,
    compose,
    createStore,
    Reducer
} from 'redux';

const reducers: {[key: string]: Reducer<any>} = {
    myReducerOne: (state: any, action: Action) => state,
    myReducerTwo: (state: any, action: Action) => state
};
const initialState: Map                       = Map({
    myReducerOne: Map({
        myInfoOne: 'abc',
        myInfoTwo: '123',
    }),
    myReducerTwo: Map({
        myInfoThree: 'def',
        myInfoFour:  '456',
    })
});
const immutableRecords: Record<string, any>[] = [];
const transforms: TransformType[]             = [];
const middlewares: Middleware[]               = [];
const merger: MergerType                      = immutableMerger;
const serializer: SerializerType              = new ImmutableSerializer(immutableRecords);
const storage: StorageType                    = new LocalstorageStorage(serializer, transforms);

const store = createStore(
    Object.keys(reducers).length ? combineReducers(reducers, Map()) : (state: any, action: Action) => state,
    initialState,
    compose(
        persistableEnhancer({
            merger:     merger,
            storage:    storage,
            storageKey: 'my-store',
            version:    1
        }),
        applyMiddleware(...middlewares)
    )
);

Merged storage

Allows to store parts of the state to different storages, e.g. to store basic settings like the locale in permanent storage but others like session id to temporary storage. Merging is applied in the order the storages where added (from left to right in terms of e.g. Object.assign()) meaning the same key from the second storage overrides the one from the first storage. Filtering the data to store is up to the developer, it is applied by state transforms upon persisting (right before serialization) and loading (right after de-serialization and migrations).

import createFilter from '@actra-development-oss/redux-persist-transform-filter-immutable';
import {
    immutableMerger,
    LocalstorageStorage,
    MergedStorage,
    MergerType,
    SessionstorageStorage
} from '@actra-development-oss/redux-persistable/lib';
// ...other imports, see usage section

const merger: MergerType                   = immutableMerger;
const mergedStorage                        = new MergedStorage(Map(), merger);
const permanentTransforms: TransformType[] = [
    createFilter('myReducerOne', ['myInfoOne'], ['myInfoOne'], 'whitelist'),
    createFilter('myReducerTwo', ['myInfoThree'], ['myInfoThree'], 'whitelist'),
];
const temporaryTransforms: TransformType[] = [
    createFilter('myReducerOne', ['myInfoTwo'], ['myInfoTwo'], 'whitelist'),
    createFilter('myReducerTwo', ['myInfoFour'], ['myInfoFour'], 'whitelist')
];
// ...other declarations, see usage section

mergedStorage.addStorage('my-permanent-storage', new LocalstorageStorage(serializer, permanentTransforms));
mergedStorage.addStorage('my-temporary-storage', new SessionstorageStorage(serializer, temporaryTransforms));

const store = createStore(
    Object.keys(reducers).length ? combineReducers(reducers, Map()) : (state: any, action: Action) => state,
    initialState,
    compose(
        persistableEnhancer({
            merger:     merger,
            storage:    mergedStorage,
            storageKey: 'my-store',
            version:    1
        }),
        applyMiddleware(...middlewares)
    )
)

Thanks to...

  • Zack Story for redux-persist that I used previously and that inspired me to build my own solution when immutable.js got effectivly unusable with v5
  • zalmoxisus for remotedev-serialize, a great serializer for immutables, and jsan, a great general-purpose JSON serializer