This lib was created for reducing pain from redux boilerplate.
npm install --save okdux
or
yarn add okdux
import { createStore } from "redux";
import { connect } from "react-redux";
import { createActions, createState, build } from "okdux";
const actions = createActions({
inc: build.action<string>()
});
const counterState = createState(0);
// different types of counters
const state = createState({ counter: countersState });
counterState.on(actions.inc, (state, p) => {
return state + 1;
});
//[optional]auto bind all actions to redux
//store is redux store
state.createStore((reducer)=> createStore(reducer, {}));
// or
const store = createStore(state.reducer, {});
state.use(store.dispatch);
countersState.select(store.getState()); // will return state from root
countersState.select(store.getState()); // will return state from root
// select only counter from root state
// this component will be reuseable and you won't care about where your reducer are placed
// also you will get types suggestions
const enhancer = connect(countersState.select(counter=>({ counter })))
// dispatch actions
// all actions are autobinded to store after using .use action
// you can assign one action to multiple stores
// to access plain action call inc.raw();
// actions are autobinded in case of
inc(1);
inc(2);
inc(2);
inc(3);
inc(8);
create state from plain object or compose from different state
const counter = createState(0);
const state = createState({ counter });
ALERT: YOU CAN PASS to createState either plain obj or map of states
this is ok
const counter = createState(0);
const counter2 = createState(0);
const state = createState({ counter, counter2 });
this is not ok
const counter = createState(0);
const counter2 = createState(0);
const state = createState({ counter, counter2, name: "6" /* not ok*/ });
const state = createState({ counter, counter2, name: createState("name") }); // this is ok
Add handler to substate
It's like building reducer but with using .on
instead of switch cases
in handler as second argument you will get action payload and you have to return new state
selects state related to your state builder
state with map is equivalent to mapFn(StateBuilder.select({}));
it will return substate related to some stateBuilder Example:
// somewhere in state file;
const counterState = createState(0);
//somewhere in component
// now you can select your counter state and don't care about counter placement in store
const enhancer = connect(countersState.select(counter => ({ counter })));
ALERT: you can have only one stateBuilder mounded to root state
const st = createState(2);
const rootSTate = createState({
st,
st2: st
}); // not ok
const makeSt = () => createState(2);
const rootSTate = createState({
st: makeSt(),
st2: makeSt()
}); // ok
reducer property it's encapsulated reducer inside state builder
makes all actions binded using on
handler autobinded to this function
so you won't have to use mapDispatchToProps
same as use
example
const state = createState(0);
state.createStore(reducer => createStore(reducer, {}));
// or simpler
state.createStore(createStore);
reset reducer value to default
same as state.on(action, ()=>initialValue)
examples
import { build, createState, createApi } from "okdux";
const counter = createState(0);
const actions = createApi(counter, {
increment(state, payload) {
return { ...state, payload };
},
decrement(state, payload) {
return { ...state, payload };
}
});