simple-selectors

Simplified Selector Functions

Usage no npm install needed!

<script type="module">
  import simpleSelectors from 'https://cdn.skypack.dev/simple-selectors';
</script>

README

Simple Selectors

Travis npm package

npm i simple-selectors --save

Simple "selectors" library, forked and heavily based on the original reselect.

In brief:

  • Selectors can compute derived data, allowing Redux to store the minimal possible state.
  • Selectors are efficient. A selector is not recomputed unless one of its arguments change.
  • Selectors are composable. They can be used as input to other selectors.

For more detailed information about the rationale behind selectors, please visit the reselect documentation.

Differences from Reselect:

  • A selector takes a maximum of two arguments, (state) or (state, props) - variadic args are not permitted.
  • createSelector also covers createStructuredSelector when passed an object.
  • createSimpleSelector creates a non-memoized selector for situations where memoization is not helpful
  • Simplified memoization, only the equality operator can be configured via memoizedSelectorCreator
  • Simpler internals for easier debugging

API

createSelector(...inputSelectors | [inputSelectors], resultFunc)

createSelector(structuredSelector)

Takes one or more selectors, or an array of selectors, computes their values and passes them as arguments to resultFn.

createSelector determines if the value returned by an input-selector has changed between calls using reference equality (===). Inputs to selectors created with createSelector should be immutable.

Selectors created with createSelector have a cache size of 1. This means they always recalculate when the value of an input-selector changes, as a selector only stores the preceding value of each input-selector.

const mySelector = createSelector(
  state => state.values.value1,
  state => state.values.value2,
  (value1, value2) => value1 + value2
)

// You can also pass an array of selectors
const totalSelector = createSelector(
  [
    state => state.values.value1,
    state => state.values.value2
  ],
  (value1, value2) => value1 + value2
)

It can be useful to access the props of a component from within a selector. When a selector is connected to a component with connect, the component props are passed as the second argument to the selector:

const abSelector = (state, props) => state.a * props.b

// props only (ignoring state argument)
const cSelector =  (_, props) => props.c

// state only (props argument omitted as not required)
const dSelector = state => state.d

const totalSelector = createSelector(
  abSelector,
  cSelector,
  dSelector,
  (ab, c, d) => ({
    total: ab + c + d
  })
)

Structured Selector:

createSelector may also take an object whose properties are input-selectors and returns a structured selector. This "structured selector" returns an object with the same keys as the inputSelectors argument, but with the selectors replaced with their values.

const mySelectorA = state => state.a
const mySelectorB = state => state.b

const structuredSelector = createSelector({
  x: mySelectorA,
  y: mySelectorB
})

const result = structuredSelector({ a: 1, b: 2 }) // will produce { x: 1, y: 2 }

Structured selectors can be nested:

const nestedSelector = createSelector({
  subA: createSelector({
    selectorA,
    selectorB
  }),
  subB: createSelector({
    selectorC,
    selectorD
  })
})

createSimpleSelector(...inputSelectors | [inputSelectors], resultFunc)

createSimpleSelector(structuredSelector)

Same API as createSelector, however it does not perform any memoization on the selector.

memoizedSelectorCreator(equalityCheck)

memoizedSelectorCreator can be used to make a customized version of createSelector.

The equalityCheck determines how equality is used when checking against previous values.

import shallowEquals from 'shallow-equals'

function shallowish(maxDepth = 1) {
  return function eq(a, b, currentDepth = 0) {
    if (a === b) return true
    if (currentDepth >= maxDepth) return false
    if ((Array.isArray(a) && Array.isArray(b)) || (isPlainObject(a) && isPlainObject(b))) {
      return shallowEquals(a, b, (a, b) => eq(a, b, currentDepth + 1));
    }
    return false
  }
}

const customSelector = memoizedSelectorCreator(shallowish(2))

customSelector(selectorA, selectorB, (a, b) => a.concat(b))

License

MIT