immutable-selectors
v1.0.5
Published
Converts a nested objects tree to tree of selector-functions, which can be used for convenient data access and modifications
Downloads
12
Maintainers
Readme
immutable-selectors
This package is used for comfort reusable access to parts of deep nested immutable structures. It also allows you to make modification of this structures.
Usage
Example immutable structure
const state = Immutable.fromJS({
moduleA: {
foo: {
id:100500,
deep:{
val:500
},
message:'SomeStringMessage'
},
bar:{}
},
moduleB:{}
});
Create selector tree Describe nested selector - object with properties you want to get access:
const selectors = {
foo:{
deep:{val:{}},
message:{}
}
}
Make selectors from this object:
import extendSelecors from 'immutable-selectors';
extendSelecors(selectors, ['moduleA']);
extendSelecors(selectorsTree, [path]) function recursively converts each key in object to a function(state), which returns corresponding part of immutable structure. At the same time, it saves the hierarchy. It is not returns a new selector - object, but it converts selectors object itself. This allows to use intelliSence in most of IDEs.
Use selector
console.log(selectors.foo.message(state)); //SomeStringMessage
console.log(selectors.foo(state)); // Map { "id": 100500, "deep": Map { "val": 500 }, "message": "SomeStringMessage" }
console.log(selectors.foo(state).get('message')); // SomeStringMessage
console.log(selectors.foo.deep.val(state)); // 500
flat option: Each unique key of selectors-tree is dublicated in selectors.flat object:
console.log(selectors.flat.val(state)); //500
console.log(selectors.flat.message(state)); // SomeStringMessage
root option:
const moduleAData = selectors.root(state);
console.log(moduleAData.getIn(['foo', 'id'])); //100500
Modifications Each selector-function in tree has replace(state, newValue) child function, which returns new immutable structure with changed corresponding part.
var newState = selectors.foo.message.replace(state, 'updated message');
console.log(newState.getIn(['moduleA','foo', 'message'])); //updated message
var newState = selectors.flat.val.replace(state, 'new value');
console.log(newState.getIn(['moduleA','foo', 'deep', 'val'])); //new value
var part = selectors.foo(state).asMutable();
part.setIn(['deep', 'val'], 'fivehundred');
var newState = selectors.foo.replace(state, part.asImmutable());
console.log(newState.getIn(['moduleA','foo', 'deep', 'val']));//fivehundred
Parameters
It is possible to use selectors for collection items access (Lists and Maps). You should specify param property in selector-object at collection level.
Example immutable structure
const state = Immutable.fromJS({
moduleA: {
bar: {
listItems: [
{
key: 100,
caption: 'firstListItem',
deep:{ description:'someText'}
},
{
key: 200,
caption: 'secondLIstItem'
}
]}}
});
Create selector tree
const selectors = {
bar:{
listItems:{
param:'x',
key:{},
caption:{},
deep:{description:{}}
}
}
}
extendSelecors(selectors, ['moduleA']);
Use
console.log(selectors.bar.listItems.caption(state, '1')); //secondLIstItem
console.log(selectors.flat.key(state, '0')); //100
console.log(selectors.flat.description(state, '0')); //someText
console.log(selectors.bar.listItems(state, '1'));//Map { "key": 200, "caption": "secondLIstItem" }
console.log(selectors.bar.listItems(state));//List [ Map { "key": 100, "caption":...
Modifications Use third parameter of replace function to specify collection item.
var newState = selectors.bar.listItems.caption.replace(state, 'updated-first', '0');
console.log(newState.getIn(['moduleA', 'bar', 'listItems', '0', 'caption'])); // updated-first
Use with redux
One of use-cases is to replace redux reducers with action-creators, which generates new global state. Example of action-creator:
export function showMessage(message) {
return function (dispatch, getState) {
dispatch({
type: 'show message',
setState: selectors.message.replace(getState(), message)
});
};
}
Root reducer:
function setStateReducer(state = initialState, action) {
if (action.setState) {
return action.setState;
} else {
return state;
// return combinedReducers(state, action); // You can mix this pattern with classical combineReducers - function.
}
}
Example of using immutable-selectors with redux without reducers.