A Redux Middleware used for storing state in either local or session strorage.
npm install --save browserstoragemiddlware
This package has two main exports: createBrowswerStorageMiddleware
and rehydrateStore
. It is totally optional to use rehydrateStore
and instead use your own rehydrate method, if you want to do this checkout the docs for rehydrate store below.
The default type of storage used is sessionStorage
.
Browser storage capacities vary by browser, storage type and host. Use this handy storage capacity calculator for more precise and browser + host specific storage capacities. If you want to learn more about the differences between local and session storage refer to this.
The middleware constructor is a generic and expects two types
- Your
State
type - A type union of the types for each value to be stored in the browser. Using any is fine for simple cases - but if you add a custom serialize method it can be very useful to use a type union.
Basic usage for a single module:
type State = {
module1: { key1: string, key2: number[], key3: boolean },
...
};
const middleware = createBrowswerStorageMiddleware<State, string>('module1', ['key1', 'key3'])
If you have multiple modules:
type State = {
module1: { key1: string, key2: boolean },
module2: { key1: number, key2: string }
};
const module1Middleware = createBrowswerStorageMiddleware<State, string>('module1', ['key1'])
const module2Middleware = createBrowswerStorageMiddleware<State, string | number>('module2', ['key1', 'key2'])
This method is used to parse the values stored in the browser and initialize the redux store with those values. This method is also generic and expects a single type: A type union of the types for each value stored in the browser. Using any is fine for simple cases - but if you add a custom parse method it can be very useful to use a type union.
The only required argument is the list of modules with values stored in the browser.
Basic usage:
const hydratedState = rehydrateStore<string | number>([module1, module2, ...])
A full example of usage with createBrowserStorageMiddleware
import {
createStore,
applyMiddleware,
compose,
} from 'redux'
type State = {
module1: { key1: string, key2: boolean },
module2: { key1: number, key2: string }
};
const module1Middleware = createBrowswerStorageMiddleware<State, string>('module1', ['key1'])
const module2Middleware = createBrowswerStorageMiddleware<State, string | number>('module2', ['key1', 'key2'])
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
const store = createStore(
reducer,
rehydrateStore<string | number>(['module1', 'module2']),
composeEnhancers(
applyMiddleware(
module1Middleware,
module2Middleware
),
)
)
export type MiddlewareConfig<T> = {
serialize: (key: string, value: T) => string,
interval: number,
storage: 'local' | 'session'
}
Where T is the type union of the types for each value stored in browser storage. For most simple cases you can set this to any it is really only going to useful if you want to write custom serialize method.
This is the throttle interval.
Expects a number in ms
. Defaults to 0
The serialization method to be used when storing the values in the browser.
Expects a method with type (key: string, value: T) => string
where T is the type union of the types for each value stored in browser storage
The default serialize method is
JSON.stringify(value, (_, subVal) => {
if(subVal instanceof Set) {
return {arr: Array.from(subVal), _isSet: true}
}
return subVal
}
The transform for sets is added due to JSON.stringify
not supporting sets.
A custom error handler. Expected a method with one argument of type Error
.
By default any runtime errors encountered will be thrown as expected.
The type of browser storage to use.
Expects either 'session' or 'local'. Defaults to 'session'
export type RehydratorConfig<S, T> = {
parse: (value: string) => T,
initialState?: Partial<S>,
storage: 'local' | 'session'
}
The inital value for your entire state. This will be merged using ramda's mergeDeep
method so nested objects will be merged recursively.
Expects a partial of your state. Defaults to {}
The parse method to be used when retrieving stored values from the browser.
Expects a method with type (value: string) => T
where T is the type union of the types for each value stored in browser storage
The default parse method is
JSON.parse(value, (_, subValue) => {
if(typeof subValue === 'object') {
if(subValue['_isSet']) {
return new Set(subValue['arr'])
}
}
return subValue
})
The default accounts for JSON.parse
not supporting sets and will instead parse any objects that look like {arr: any[], _isSet: true }
as new Set(arr)
.
A custom error handler. Expected a method with one argument of type Error
.
By default any runtime errors encountered will be thrown as expected.
The type of browser storage to use.
Expects either 'session' or 'local'. Defaults to 'session'
MIT