@rakoon-badshah/dynamic-redux
This is a library to create Redux stores that can have additional reducers dynamically attached at runtime.
It has the following functions from the following respective packages:
- createStore,applyMiddleware,compose : redux-dynamic-reducers Package,
- combineReducers: redux,
- get,set,delete : dot-prop-immutable.
Install
$ npm install @rakoon-badshah/dynamic-redux
Why this Library?
A Redux store's state tree is created from a single reducer function. combineReducers
is the mechanism to compose many reducer functions into a single reducer that can be used to build a hierarchical the state tree. It is not possible to modify the reducer function after the store has been initialised.
This library allows you to attach new reducer functions after the store is initialised. This is helpful if you want to use a single global store across a lazily loaded application where not all reducers are available at store creation.
How to use
1. Create the store
The createStore
function replaces the Redux createStore
function. It adds the attachReducers()
function to the store object. It also supports all the built in optional parameters:
import { combineReducers,createStore } from '@rakoon-badshah/dynamic-redux'
...
const reducer = combineReducers({ staticReducer1, staticReducer2 })
const store = createStore(reducer)
const store = createStore(reducer, { initial: 'state' })
const store = createStore(reducer, applyMiddleware(middleware))
const store = createStore(reducer, { initial: 'state' }, applyMiddleware(middleware))
2. Dynamically attach a reducer
Not using redux-subspace
Call attachReducers
on the store with your dynamic reducers to attach them to the store at runtime:
store.attachReducers({ dynamicReducer })
Multiple reducers can be attached as well:
store.attachReducers({ dynamicReducer1, dynamicReducer2 })
Reducers can also be added to nested locations in the store:
store.attachReducers({
some: {
path: {
to: {
dynamicReducer
}
}
}
} )
store.attachReducers({ 'some.path.to': { dynamicReducer } } } })
store.attachReducers({ 'some/path/to': { dynamicReducer } } } })
3. Use the Get-Set Helper functions to easily access and update the state in reducers
This library implements 3 helper functions:
get(object, path) --> value
set(object, path, value) --> object
delete(object, path) --> object
usage
var dotProp = require('dot-prop-immutable');
get
Access a nested property by a dot path
// Getter
dotProp.get({foo: {bar: 'unicorn'}}, 'foo.bar')
//=> 'unicorn'
dotProp.get({foo: {bar: 'a'}}, 'foo.notDefined.deep')
//=> undefined
dotProp.get({foo: {bar: 'a'}}, 'foo.notDefined.deep', 'default value')
//=> default value
dotProp.get({foo: {'dot.dot': 'unicorn'}}, 'foo.dot\\.dot')
//=> 'unicorn'
or use a property array as a path.
// Use an array as get path
dotProp.get({foo: {'dot.dot': 'unicorn'}}, ['foo', 'dot.dot'])
//=> 'unicorn'
set
Modify a nested property by a dot path
// Setter
var obj = {foo: {bar: 'a'}};
var obj1 = dotProp.set(obj, 'foo.bar', 'b');
//obj1 => {foo: {bar: 'b'}}
var obj2 = dotProp.set(obj1 , 'foo.baz', 'x');
//obj2 => {foo: {bar: 'b', baz: 'x'}}
where obj
, obj1
, obj2
, obj3
all are different objects.
Use a function to modify the selected property, where first argument is the old value.
// Setter where value is a function (get and set current value)
dotProp.set({foo: {bar: 'a'}}, 'foo.bar', v => v + 'bc')
//=> {foo: {bar: 'abc'}}
Modify a nested array
var obj = {foo: [{ bar: 'gold-unicorn'}, 'white-unicorn', 'silver-unicorn']};
// Index into array
dotProp.set(obj, 'foo.1', 'platin-unicorn')
//=> {foo: [{bar: 'gold-unicorn'}, 'platin-unicorn', 'silver-unicorn']}
dotProp.set(obj, 'foo.0.bar', 'platin-unicorn')
//=> {foo: [{bar: 'platin-unicorn'}, 'white-unicorn', 'silver-unicorn']}
// Index into array with $end
dotProp.set(obj, 'foo.$end', 'platin-unicorn')
//=> {foo: [{ bar: 'gold-unicorn'}, 'white-unicorn', 'platin-unicorn']}
delete
Delete a nested property/array by a dot path
var obj = {foo: [{ bar: 'gold-unicorn'}, 'white-unicorn', 'silver-unicorn']};
// delete
dotProp.delete(obj, 'foo.$end');
//=> {foo: [{ bar: 'gold-unicorn'}, 'white-unicorn']}
dotProp.delete(obj, 'foo.0.bar');
//=> {foo: [{}, 'white-unicorn', 'silver-unicorn']}
Limitations
- Each dynamic reducer needs a unique key
- If the same key is used in a subsequent attachment, the original reducer will be replaced
- Nested reducers cannot be attached to nodes of the state tree owned by a static reducer