@duckness/use-redux
TypeScript icon, indicating that this package has built-in type declarations

1.0.0 • Public • Published

@duckness/use-redux

React hook for Redux store

NPM License Libraries.io dependency status for latest release, scoped npm package GitHub issues vulnerabilities npm bundle size

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:

  1. shouldSelect is not specified or null
  2. 'function' === typeof shouldSelect and true == shouldSelect(nextStoreState, prevStoreState)

shouldUpdate

Optional selectedState update filter.

useRedux will update after every redux store update and selector call if:

  1. true === shouldUpdate
  2. 'function' === typeof shouldUpdate and true == shouldUpdate(nextSelectedState, prevSelectedState)
  3. shouldUpdate is not specified or null and nextSelectedState !== 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.

  1. undefined === payloadTransformer - use supplied payload.
const onAction = useDispatchAction(store, myAction)
onAction('PAYLOAD')
// => dispatch { type: 'MY_ACTION', payload: 'PAYLOAD' }
  1. 'function' === typeof payloadTransformer - transform payload.
const onAction = useDispatchAction(store, myAction, str => str.toLowerCase())
onAction('PAYLOAD')
// => dispatch { type: 'MY_ACTION', payload: 'payload' }
  1. any other values for payloadTransformer - use payloadTransformer 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:

  1. selector - combined selector
  2. shouldUpdate - selectedState update filter (see above)
  3. areEqual - negative of shouldUpdate
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:

Readme

Keywords

Package Sidebar

Install

npm i @duckness/use-redux

Weekly Downloads

106

Version

1.0.0

License

MIT

Unpacked Size

34.5 kB

Total Files

6

Last publish

Collaborators

  • hitosu