@duckness/use-redux
v1.0.0
Published
React hook for Redux store
Downloads
231
Readme
@duckness/use-redux
React hook for Redux store
Example
import React from 'react'
import useRedux from '@duckness/use-redux'
const counterSelector = (state => state.counter || 0)
export default function Counter() {
const counter = useRedux(store, counterSelector)
return <span>[ {counter} ]</span>
}
Table of Contents
useRedux
const selectedState = useRedux(store, selector, shouldUpdate?, shouldSelect?)
store
Redux store to subscribe to.
selector
Select relevant data from store state.
function selector(state) {
// ... calculate selectedState from state
return selectedState
}
shouldSelect
Optional select filter. This optimization helps to avoid expensive calculations in selector
.
selector
will be called on every redux store update if:
shouldSelect
is not specified ornull
'function' === typeof shouldSelect
andtrue == shouldSelect(nextStoreState, prevStoreState)
shouldUpdate
Optional selectedState update filter.
useRedux
will update after every redux store update and selector
call if:
true === shouldUpdate
'function' === typeof shouldUpdate
andtrue == shouldUpdate(nextSelectedState, prevSelectedState)
shouldUpdate
is not specified ornull
andnextSelectedState !== prevSelectedState
useDispatchAction
Binds actionCreator to store.dispatch
.
const onAction = useDispatchAction(store, actionCreator, payloadTransformer?)
// ...
onAction(payload)
// => dispatch action with payload
actionCreator
function myAction(payload) {
type: 'MY_ACTION',
payload: payload
}
payloadTransformer
Optional payload transformer.
undefined === payloadTransformer
- use supplied payload.
const onAction = useDispatchAction(store, myAction)
onAction('PAYLOAD')
// => dispatch { type: 'MY_ACTION', payload: 'PAYLOAD' }
'function' === typeof payloadTransformer
- transform payload.
const onAction = useDispatchAction(store, myAction, str => str.toLowerCase())
onAction('PAYLOAD')
// => dispatch { type: 'MY_ACTION', payload: 'payload' }
- any other values for
payloadTransformer
- usepayloadTransformer
as payload.
const onAction = useDispatchAction(store, myAction, null)
onAction('PAYLOAD')
// => dispatch { type: 'MY_ACTION', payload: null }
Third option is useful when using useDispatchAction
as a callback for DOM events.
function increment(amount) {
return { type: 'INC', payload: null == amount ? 1 : amount }
}
const onInc = useDispatchAction(store, increment, null)
// <button onClick={onInc}>INC</button>
// onInc will be called with { payload: null } instead of { payload: event }
useDispatch
useDispatch(store, dispatcher, deps)
Example:
const onMultiAction = useDispatch(store, (dispatch, amount) => {
for (let i = 0; i < amount; i++) {
dispatch( actionCreator(i) )
}
}, [actionCreator])
// ...
onMultiAction(10)
// => dispatch 10 actions
function SetStatusButton({ status = 'ready' } = {}) {
const onClick = useDispatch(
store,
dispatch => {
dispatch(actionSetStatus(status))
},
[status]
)
return <button onClick={onClick}>{status}</button>
}
combineSelectors
Produces three functions from a map of selectors:
selector
- combined selectorshouldUpdate
- selectedState update filter (see above)areEqual
- negative ofshouldUpdate
const { selector: actionCounterSelector, shouldUpdate: shouldUpdateActionCounter } = combineSelectors({
actionsDispatched: CounterDuck.select.actionsDispatched,
lastActionDispatchedAt: CounterDuck.select.lastActionDispatchedAt
})
export default function ActionCounter() {
const { actionsDispatched, lastActionDispatchedAt } = usePool(
CounterPool,
actionCounterSelector,
shouldUpdateActionCounter
)
return (
<span>
(ACTIONS: {actionsDispatched}, LAST: {lastActionDispatchedAt})
</span>
)
}
Passing custom selectedStatesEqual
function that compares selected states
combineSelectors(selectorsMap, { selectedStatesEqual } = {})
selectedStatesEqual(selectorKey, nextSelectedState[selectorKey], prevSelectedState[selectorKey]): Boolean
connect
Creates HOC connected to Redux store.
connect(store, selector, shouldUpdate, shouldSelect, dispatch = store.dispatch) => (Component, ?mapToProps) => ConnectedComponent
store
, shouldUpdate
, shouldSelect
are the same arguments used in useRedux
.
selector
is the same function used in useRedux
but with ownProps
added: selector(state, ownProps)
mapToProps
is an optional props mapper in form of
(selectedState, ownProps, dispatch) => componentProps
Example:
import { connect, combineSelectors } from '@duckness/use-redux'
import TodoList from '../../components/TodoList'
import TodoListPool, { TodoDuck } from '../TodoListPool'
const { selector, shouldUpdate } = combineSelectors({
// we should wrap selector because TodoDuck.select.visibleTodos expects (state, duckFace) with duckFace added by Duck,
// but connected selector is called as (state, ownProps) that would lead to (state, ownProps, duckFace) call.
todos: state => TodoDuck.select.visibleTodos(state)
})
export default connect(
TodoListPool.store,
selector,
shouldUpdate
)(TodoList, (selectedState, ownProps, dispatch) => {
return {
...ownProps,
...selectedState,
onToggleTodo: id => void dispatch(TodoDuck.action.toggleTodo(id))
}
})
@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