kilkelly / redux-localstorage-simple

Save and load Redux state to and from LocalStorage.
MIT License
131 stars 23 forks source link
localstorage redux

Redux-LocalStorage-Simple

Save and load Redux state to and from LocalStorage.

Installation

npm install --save redux-localstorage-simple

Usage Example (ES6 code)

import { applyMiddleware, createStore } from "redux"
import reducer from "./reducer"

// Import the necessary methods for saving and loading
import { save, load } from "redux-localstorage-simple"

/*
    Saving to LocalStorage is achieved using Redux 
    middleware. The 'save' method is called by Redux 
    each time an action is handled by your reducer.
*/    
const createStoreWithMiddleware 
    = applyMiddleware(
        save() // Saving done here
    )(createStore)

/*
    Loading from LocalStorage happens during
    creation of the Redux store.
*/  
const store = createStoreWithMiddleware(
    reducer,    
    load() // Loading done here
)    

API

save([Object config])

Saving to LocalStorage is achieved using Redux middleware and saves each time an action is handled by your reducer. You will need to pass the save method into Redux's applyMiddleware method, like so...

applyMiddleware(save())

See the Usage Example above to get a better idea of how this works.

Arguments

The save method takes a optional configuration object as an argument. It has the following properties:

{
    [Array states],
    [Array ignoreStates]
    [String namespace],
    [String namespaceSeparator],
    [Number debounce],
    [Boolean disableWarnings]
}

Examples

Save entire state tree - EASIEST OPTION.

save()

Save specific parts of the state tree.

save({ states: ["user", "products"] })

Save entire state tree except the states you want to ignore.

save({ ignoreStates: ["miscUselessInfo1", "miscUselessInfo2"] })

Save the entire state tree under the namespace "my_cool_app". The key "my_cool_app" will appear in LocalStorage.

save({ namespace: "my_cool_app" })

Save the entire state tree only after a debouncing period of 500 milliseconds has elapsed

save({ debounce: 500 })

Save specific parts of the state tree with the namespace "my_cool_app". The keys "my_cool_app_user" and "my_cool_app_products" will appear in LocalStorage.

save({
    states: ["user", "products"],
    namespace: "my_cool_app"
})

Save specific parts of the state tree with the namespace "my_cool_app" and the namespace separator "::". The keys "my_cool_app::user" and "my_cool_app::products" will appear in LocalStorage.

save({
    states: ["user", "products"],
    namespace: "my_cool_app",
    namespaceSeparator: "::"
})

load([Object config])

Loading Redux state from LocalStorage happens during creation of the Redux store.

createStore(reducer, load())    

See the Usage Example above to get a better idea of how this works.

Arguments

The load method takes a optional configuration object as an argument. It has the following properties:

{
    [Array states],    
    [String namespace],
    [String namespaceSeparator],
    [Object preloadedState],
    [Boolean disableWarnings]
}

Examples

Load entire state tree - EASIEST OPTION.

load()

Load specific parts of the state tree.

load({ states: ["user", "products"] })

Load the entire state tree which was previously saved with the namespace "my_cool_app".

load({ namespace: "my_cool_app" })

Load specific parts of the state tree which was previously saved with the namespace "my_cool_app".

load({ 
    states: ["user", "products"],
    namespace: "my_cool_app"
})

Load specific parts of the state tree which was previously saved with the namespace "my_cool_app" and namespace separator "::".

load({ 
    states: ["user", "products"],
    namespace: "my_cool_app",
    namespaceSeparator: "::"
})

combineLoads(...loads)

If you provided more than one call to save in your Redux middleware you will need to use combineLoads for a more intricate loading process.

Arguments

Example

Load parts of the state tree saved with different namespaces. Here are the save methods in your Redux middleware:

applyMiddleware(
    save({ states: ["user"], namespace: "account_stuff" }),
    save({ states: ["products", "categories"], namespace: "site_stuff" })
)

The corresponding use of combineLoads looks like this:

combineLoads( 
    load({ states: ["user"], namespace: "account_stuff" }),
    load({ states: ["products", "categories"], namespace: "site_stuff" })
)

clear([Object config])

Clears all Redux state tree data from LocalStorage. Note: only clears data which was saved using this module's functionality

Arguments

The clear method takes a optional configuration object as an argument. It has the following properties:

{
    [String namespace],
    [Boolean disableWarnings]
}

Examples

Clear all Redux state tree data saved without a namespace.

clear()

Clear Redux state tree data saved with a namespace.

clear({
    namespace: "my_cool_app"
})  

Advanced Usage

In a more complex project you may find that you are saving unnecessary reducer data to LocalStorage and would appreciate a more granular approach. Thankfully there is a way to do this.

First let's look at a normal example. Let's say you have a reducer called settings and its state tree looks like this:

const settingsReducerInitialState = {
    theme: 'light',
    itemsPerPage: 10
}

Using redux-localstorage-simple's save() method for the settings reducer would look like this:

save({ states: ["settings"] })

This saves all of the settings reducer's properties to LocalStorage. But wait, what if we really only care about saving the user's choice of theme and not itemsPerPage. Here's how to fix this:

save({ states: ["settings.theme"] })

This saves only the theme setting to LocalStorage. However this presents an additional problem, if itemsPerPage is not saved won't my app crash when it can't find it upon loading from LocalStorage?

Yes in most cases it would. So to prevent this you can use the preloadedState argument in the load() method to provide some initial data.

load({
    states: ["settings.theme"],
    preloadedState: {
        itemsPerPage: 10        
    }
})

Also note in the above example that since settings.theme was specified in the load() method we must also mirror this exactly in the save() method. This goes for all states you specify using the granular approach.

So if you have:

save({ states: ["settings.theme"] })

You must also have:

load({ states: ["settings.theme"] })

Testing

To run tests for this package open the file 'test/test.html' in your browser. Because this package uses LocalStorage we therefore need to test it in an environment which supports it i.e. modern browsers.

Removal of support for Immutable.js data structures

Support for Immutable.js data structures has been removed as of version 1.4.0. If you require this functionality please install version 1.4.0 using the following command:

npm install --save redux-localstorage-simple@1.4.0

Feedback

Pull requests and opened issues are welcome!

License

MIT