Simple and expressive way to bind redux state to localStorage.
Existing libraries that bind redux state to localStorage for the most part are more complicated than they should and do unnecessary dehydrations. Morever they are heavily dependent on implementation details of redux which limits version compatibility.
This module is a an expressive way to define which properties of your reducers state needs to be persisted and synced with localStorage. Essentially you create a stencil
by providing an object(your reducer state) that can potentially hold Tattoo
instances. A Tattoo
is just a placeholder with a default value and can be used to mark which properties needs to be peristed/synced.
npm install --save redux-tattoo
reducer.js
import { LOGIN_SUCCESS, LOGIN_FAILURE } from "./constants";
import { stencil, Tattoo } from "redux-tattoo";
// create Tattoo with default value of the relevant property
const sessionTattoo = new Tattoo({});
// create a stencil and define which properties will persist/load to/from localStorage
// essentially any property inside the stencil that is of type Tattoo will be
// stored to localStorage and upon initialization of the initialState if there is already
// a value stored for that property it will be loaded instead of the Tattoo default value
export const initialState = stencil(
{
session: sessionTattoo, // It evaluates to the last stored value in localStorage otherwise to the default value
},
"user" // optional namespace selector
);
const reducer = (state = initialState, action) => {
let newState;
switch (action.type) {
case LOGIN_SUCCESS:
newState = { ...state, session: action.session };
break;
case LOGOUT_SUCCESS:
newState = { ...state, session: sessionTattoo.default };
break;
default:
newState = state;
}
return newState;
};
export default reducer;
The namespace is a selector path that points to the field of the targeted reducer state in the redux store.
In the example above we use the 'user' namespace. This will target the user property of the current redux store state
const reduxStoreState = store.getState();
console.log(reduxStoreState);
// printed value of reduxStoreState
{
user: {
session: {}, // this is the targeted property from the code above
}
}
We can further target nested properties by defining dot seperated paths e.g user.session
.
In order to listen for state changes and update the localStorage accordingly we need to attach
redux-tattoo to our applications redux store.
import reduxTattoo from 'redux-tatoo';
import { createStore } from 'redux';
const store = createStore(...);
reduxTattoo.attach(store, {throttleInterval: 200});
As we can see it also provides an optional throttling mechanism in order to avoid unnecessary writes to localStorage since this is a synchronous operation.
export default { stencil, Tattoo, attach };
A function that syncs all Tattoo
properties from the reducer state with the localStorage object.
reducerInitialState - [Object]
namespace - {Optional}[String]
The synced reducer state object with the localStorage.
A class that instantiates Tattoos. Tattoos are used by a stencil
to mark which properties will be synced in localStorage.
defaultValue - [Object]
A functions that attaches redux-tattoo to the reduxStore in order to listen for state changes.
reduxStore - [Object]
options - {Optional}[Object] of format: { throttleInterval:[Integer] in millis}
npm test