Duckness Pool - @duckness/duck + Redux
npm install @duckness/pool@duckness/pool 





``js
import Pool from '@duckness/pool'
import CounterDuck from './ducks/CounterDuck'
const CounterPool = Pool({
buildStore: ({ initialCounter = 0 } = {}) => {
return { counter: initialCounter }
}
})
CounterPool.addDuck(CounterDuck)
CounterPool.build({initialCounter: 0})
CounterPool.store
// => [redux store]
`
- Example
- API
- Create Pool
- buildStore
- default buildStore
- buildRootReducer
- default buildRootReducer
- .addDuck(duck)
- .preReducer(reducer)
- .postReducer(reducer)
- .build(props)
- .store
- .dispatch(...)
- [.reduce([state,] action)](#reducestate-action).select(?selector)
- .fetch(selector, ?resolver)
- .trigger(selector, callback, ?resolver)
- .setErrorReporter(reporterFn)
- .reportError(error)
- .addMiddleware(middleware)
- .addStream(poolStream)
- Pool Streams - Pool plugins
- PoolStream
- API.ducks
- .getDuckByName(duckPath)
- duckPath
- :.middlewares
- .streams
- .props
-
- Examples
- @Duckness packages:
`js`
const myPool = Pool({
?poolName: String, // pool name, default is 'pool'
?ducks: Array
?middlewares: Array
?streams: Array
?buildStore: (props, { refProps, refDucks, refErrorReporter }) => storeState, // build initial store state
?buildRootReducer: ({ refDucks, refErrorReporter }) => rootReducer // build custom root reducer from ducks instead of default root reducer
})
Optional function to build init store state
(props, { refProps, refDucks, refReducers, refErrorReporter }) => storeState
* props are passed to pool when pool.build(props) are called.refProps.current
* - props passed to pool.build(props) functionrefDucks.current
* - current array of ducks.refReducers.root
* - pool root reducerrefReducers.pre
* - pool pre reducerrefReducers.post
* - pool post reducerrefErrorReporter.current
* - current error reporter function.
#### default buildStore
If not specified store state will be set to {}.
*
ducks - array of ducks
* refProps.current - props passed to pool.build(props) function
* refDucks.current - current array of ducks.
* refReducers.pre - pool pre reducer
* refReducers.post - pool post reducer
* refErrorReporter.current - current error reporter function.#### default
buildRootReducerDefault root reducer will combine all duck root reducers via
`js
ducks.reduce((state, duck) => {
return duck(state, action)
}, state)
`
with every duck root reducer wrapped in try/catch returning unmodified state in case of exception inside duck root reducer..addDuck(duck)Add duck to pool.
`js
MyPool.addDuck(myDuck)
`.preReducer(reducer)Add pool pre reducer.
Pre reducers will run BEFORE duck reducers and will receive all actions.
Will replace previously set pre reducer.
`js
MyPool.preReducer(function globalPreReducer(state, action) {/ ... /} )
`.postReducer(reducer)Add pool post reducer.
Post reducers will run AFTER duck reducers and will receive all actions.
Will replace previously set post reducer.
`js
MyPool.postReducer(function globalPostReducer(state, action) {/ ... /} )
`.build(props)Build pool state from some props.
props will be passed to buildStore function.
`js
MyPool.build({ initialCounter: 0 })
`.storeReference to built redux store.
`js
MyPool.store.subscribe(/ ... /)
`.dispatch(...)1. Dispatches an action (action is a plain object).
`js
const action = { type: 'actionType', payload: {} }
MyPool.dispatch(action)
`2. Dispatches and action from 'poolName/duckName' duck.
This will first look for a duck by 'duckName' and current 'poolName', then duck's action creator by 'actionName' and call it with 'actionParams' to build action to dispatch.
`js
MyPool.dispatch('duckName', 'actionName', ...actionParams)
`Example:
`js
const MyDuck = Duck('myDuck', 'myPool')
MyDuck.action('someAction')const MyPool = Pool({ poolName: 'myPool' })
MyPool.addDuck(MyDuck)
MyPool.dispatch('myDuck', 'someAction', ...actionParams)
// equal to
MyPool.dispatch(MyDuck.action.someAction(...actionParams))
`3. Dispatches and action from 'customPoolName/duckName' duck.
This will first look for a duck by 'duckName' and 'poolName', then duck's action creator by 'actionName' and call it with 'actionParams' to build action to dispatch.
`js
MyPool.dispatch(['customPoolName', 'duckName'], 'actionName', ...actionParams)
`
.reduce([state,] action)Reduce state with action. Does not change pool's store. Can be used to look ahead what the state will be after dispatching an action.
`js
MyPool.reduce(action) // reduce pool's store state
MyPool.reduce(state, action) // reduce custom state
`.select(?selector)Select something from store. Returns store state if
selector undefined.
`js
MyPool.select(MyDuck.select.something)
// => selected value
MyPool.select()
// => current store state
`.fetch(selector, ?resolver)Returns
Promisefunction resolver(selected, resolve, prevSelected)Fetch value from the store:
- first
selector is called to produce selected value
- if resolver is defined: selected value is passed to resolver with previous selected value (undefined for the first run) and resolve function that can be used to resolve this fetch
- if resolver is not defined: selected value will be resolved if it is not undefined
- if nothing was resolved: repeat when store is updated (after next action dispatch).fetch will subscribe to store updates (if it was not resolved after first select) and unsubscribe when it is resolved.`js
// resolves with items when items are loaded into store or are already present
const items = await ListPool.fetch(ItemsDuck.select.items)// resolves when counter is reset, returning counter value before reset
const counterResetFrom = await MyPool.fetch(
state => state.counter,
(selected, resolve, prevSelected) => {
if (null != prevSelected && 0 !== prevSelected && 0 === selected) {
resolve(selected)
}
}
)
`.trigger(selector, callback, ?resolver)Returns clear trigger function.
function callback(selected)function resolver(selected, resolve, prevSelected)Trigger
callback every time:
- selected value changes (resolver is undefined)
- or resolver calls resolvetrigger calls resolver first time trigger is set and later on store updates.To unsubscribe call clear trigger function.
`js
// console.log value for 10 seconds
const clearTrigger = MyPool.trigger(
MyDuck.select.someValue,
console.log
)
setTimeout(clearTrigger, 10000)
`.setErrorReporter(reporterFn)Set exception reporter function. Will also overwrite errorReporters set in ducks.
`js
MyPool.setErrorReporter(error => {
window.Sentry.captureException(error)
})
`.reportError(error)Call assigned error reporter
`js
MyPool.reportError(new Error('Clean pool!'))
`.addMiddleware(middleware)Add custom Redux middleware (applied on
.build)Pool Streams - Pool plugins
Pool Stream is a Pool plugin that can add middlewares to Redux store. One example is @duckness/pool-saga-stream that adds @duckness/saga support to Pool (ducks can have Redux Sagas).
$3
Adds Pool Stream to Pool
$3
`js
{
// array of middlewares for Redux store
middlewares({ refDucks, refProps, refReducers, refErrorReporter }) {
// refDucks.current - current array of ducks
// refProps.current - props passed to build function
// refReducers.root - root reducer function
// refReducers.pre - pool pre reducer function
// refReducers.post - pool post reducer function
// refErrorReporter.current - current error reporter function
// ...
return [...streamMiddlewares]
},
// called before redux store is built
beforeBuild({ refDucks, refProps, refReducers, refErrorReporter }) {
// refDucks.current - current array of ducks
// refProps.current - props passed to build function
// refReducers.root - root reducer function
// refReducers.pre - pool pre reducer function
// refReducers.post - pool post reducer function
// refErrorReporter.current - current error reporter function
// ...
},
// called after redux store is built
afterBuild({ refStore, refDucks, refProps, refReducers, refErrorReporter }) {
// refStore.current - current Redux store
// refDucks.current - current array of ducks
// refProps.current - props passed to build function
// refReducers.root - root reducer function
// refReducers.pre - pool pre reducer function
// refReducers.post - pool post reducer function
// refErrorReporter.current - current error reporter function
// ...
}
}
`.ducksArray of added ducks (read only)
.getDuckByName(duckPath)Find added duck by it's path. Returns
null if duck is not found.$3
* Array: [poolName, duckName]
* String: duckName (use current poolName).middlewaresArray of added middlewares (read only)
.streamsArray of added streams (read only)
.props`Props used to build pool (read only)
https://github.com/hitosu/duckness/tree/master/stories
* @duckness/duck - Modular Redux Ducks hatchery
* @duckness/saga - Redux Saga extension for @duckness/duck
* @duckness/epic - Redux-Observable extension for @duckness/duck
* @duckness/pool - @duckness/duck + Redux
* @duckness/pool-saga-stream - @duckness/saga plugin for @duckness/pool
* @duckness/pool-epic-stream - @duckness/epic plugin for @duckness/pool
* @duckness/react-redux-pool - @duckness/pool + React-Redux
* @duckness/use-redux - React hook for Redux store
* @duckness/use-pool - React hook for @duckness/pool.
* @duckness/store - simple store for React components
* @duckness/reactor - reactive data flow builder