@duckness/pool
v1.0.0
Published
Duckness Pool - @duckness/duck + Redux
Downloads
238
Readme
@duckness/pool
Example
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]
Table of Contents
- Example
- API
- Create Pool
.addDuck(duck)
.preReducer(reducer)
.postReducer(reducer)
.build(props)
.store
.dispatch(...)
.reduce([state,] action)
.select(?selector)
.fetch(selector, ?resolver)
.trigger(selector, callback, ?resolver)
.setErrorReporter(reporterFn)
.reportError(error)
.addMiddleware(middleware)
- Pool Streams - Pool plugins
.ducks
.getDuckByName(duckPath)
.middlewares
.streams
.props
- Examples
- @Duckness packages:
API
Create Pool
const myPool = Pool({
?poolName: String, // pool name, default is 'pool'
?ducks: Array<Duck>, // array of pool ducks
?middlewares: Array<Middleware>, // additional middlewares for Redux store
?streams: Array<PoolStream>, // pool plugins
?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
})
buildStore
Optional function to build init store state
(props, { refProps, refDucks, refReducers, refErrorReporter }) => storeState
props
are passed to pool whenpool.build(props)
are called.refProps.current
- props passed topool.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 {}
.
buildRootReducer
Optional function for custom root reducer
(ducks, { refProps, refDucks, refReducers, refErrorReporter }) => rootReducer
ducks
- array of ducksrefProps.current
- props passed topool.build(props)
functionrefDucks.current
- current array of ducks.refReducers.pre
- pool pre reducerrefReducers.post
- pool post reducerrefErrorReporter.current
- current error reporter function.
default buildRootReducer
Default root reducer will combine all duck root reducers via
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.
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.
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.
MyPool.postReducer(function globalPostReducer(state, action) {/* ... */} )
.build(props)
Build pool state from some props. props
will be passed to buildStore
function.
MyPool.build({ initialCounter: 0 })
.store
Reference to built redux store.
MyPool.store.subscribe(/* ... */)
.dispatch(...)
- Dispatches an action (action is a plain object).
const action = { type: 'actionType', payload: {} }
MyPool.dispatch(action)
- 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.
MyPool.dispatch('duckName', 'actionName', ...actionParams)
Example:
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))
- 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.
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.
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.
MyPool.select(MyDuck.select.something)
// => selected value
MyPool.select()
// => current store state
.fetch(selector, ?resolver)
Returns Promise
function 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) andresolve
function that can be used to resolve thisfetch
- if
resolver
is not defined: selected value will be resolved if it is notundefined
- 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.
// 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
callsresolve
trigger
calls resolver
first time trigger is set and later on store updates.
To unsubscribe call clear trigger function.
// 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.
MyPool.setErrorReporter(error => {
window.Sentry.captureException(error)
})
.reportError(error)
Call assigned error reporter
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).
.addStream(poolStream)
Adds Pool Stream to Pool
PoolStream
API
{
// 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
// ...
}
}
.ducks
Array of added ducks (read only)
.getDuckByName(duckPath)
Find added duck by it's path. Returns null
if duck is not found.
duckPath
:
- Array:
[poolName, duckName]
- String:
duckName
(use current poolName)
.middlewares
Array of added middlewares (read only)
.streams
Array of added streams (read only)
.props
Props used to build pool (read only)
Examples
https://github.com/hitosu/duckness/tree/master/stories
@Duckness packages:
- @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