This is a work in progress and is in very early stages of development
redux-blocks
is a library for isolating and combining redux modules (referred to here on out as blocks).
It makes writing reusable redux code easier and more flexible.
npm install --save redux-blocks
If you know Redux then the simplest way to understand redux-blocks is to look at the tests for mount and merge.
You can also look at the real world example application code here .
A more details explanation can be found here
import {merge,mount} from 'redux-blocks';
import {selectors,actions,types,reducer} from 'your code';
import MoreReduxCode from 'some more of your code';
const mounted = mount("point")({
selectors,
actions,
types,
reducer
});
const merge(MoreReduxCode,mounted);
Redux blocks are objects with the following syntax:
{
selectors: {},
actions: {},
types: {}
reducer: function(){}
}
A simple example of an api request block looks like this:
const RequestBlock ={
types: {
REQUEST:"REQUEST",
SUCCESS:"SUCCESS"
},
selectors: {
get: state,id=>state.entities[id]
},
actions: {
request: id=>({
type: "REQUEST",
id
}),
success: entity=>({
type:"SUCCESS",
entity
})
},
reducer: function(state={entities:{}},action){
switch(action.type){
case "SUCCESS":
return {
entities: {
...state.entities,
[action.entity.id]:action.entitiy
}
}
default:
return state;
}
}
}
The redux-blocks
library provides two methods to isolate and combine blocks - mount
and merge
.
Calling mount('point')(block)
will isolate selectors and reducers to a section of
the state under point (I.E. the reducer's state
will actually be the contents in state.point
).
Type strings will have a "POINT"
prefix added to it, and any action that returns a type in types will
have the appropriate type associated with it.
If we take the previous example of a simple request block, the result of mounting
it at "point"
will look like this:
const mounted = mount('point')(RequestBlock);
mounted.types.REQUEST; // "POINT_REQUEST"
mounted.actions.request(5); // {type:"POINT_REQUEST",id:5}
mounted.actions.success({id:5,name:"me"}); // {type:"POINT_SUCCESS"...}
//state now looks like this:
mounted.reducer(); // {point:{entities:{}}}
mounted.selectors.get({
point: {
entities: {
5: {id:5, name:"me"}
}
}
}
//will return {id:5, name:"me"}
calling merge(block1,block2)
will merge blocks into a single block whose actions, selectors and types are a
combination of both modules selectors, actions and types.
The merged block's reducer is a new function that calls each reducer in turn (I.E. it composes reducers)
redux-blocks
provides support for redux-saga
. Instead of importing redux-blocks
import redux-blocks/saga
.
Once imported, merge will make sure to combine the saga
property in every block.
Mounting a block with redux-saga makes sure that any put
action overrides the type with the mounted one and
any take
action correctly registered for the mounted type.