combineSelectors(selectorMap)

combineSelectors is designed to work with mapStateToProps as provided by react-redux's connect function. It simply maps selectors to keys and returns an object containing the values.

Notice that you can supply a mix of string and functional selectors. Each selector is passed through createStateSelector before being executed.

Basic usage

Here you can see a simple selector that will return an object. Notice below that item maps to a selector that returns foo and other maps to a selector that returns baz. You might notice that 'baz' is a path selector.

It's important to note that combineSelectors accepts variable arguments. Meaning, by default it will pass both state and ownProps to every selector. See the next example if you are combining selectors that don't require access to ownProps.

import { combineSelectors } from '@comfy/redux-selectors'

const mapStateToProps = combineSelectors({
  item: state => state.foo,
  other: 'baz'
})

// ---

const state = {
  foo: 'bar',
  baz: true
}

mapStateToProps(state) // => { item: 'bar', other: true }

Ignoring props

Using combineSelectors directly with react-redux can surface some memoization issues. Consider the following.

In the example above, connect will presume that combineSelectors depends on both state and ownProps. However, if you only specify state in your mapStateToProps function, connect will only recompute values for state, ignoring ownProps. This can yield some small performance gains if your selectors do not need ownProps. If you are writing selectors that don't rely on props for any specific reason, you will want to wrap your combineSelectors call is a function that only accepts state.

The trick is that connect only knows to optimize your mapStateToProps by checking for the length of arguments provided. To take advantage of this, we need to present a version of combineSelectors that specifies only one argument.

Below you can see an example of the technique. Notice that the mapStateToProps only defines state, which means that react-redux will not recompute this selector unless state changes.

import { combineSelectors } from '@comfy/redux-selectors'

const mapStateToProps = state => combineSelectors({
  item: 'department.produce.fruits.oranges'
})(state)

const state = {
  department: {
    produce: {
      fruits: {
        apples: 1,
        oranges: 2
      }
    }
  }
}

mapStateToProps(state) // => { item: 2 }

Ignoring props with withState

Because ignoring props is a common pattern when working with react-redux, there is a helper function to make it easier. Notice below how we wrap combineSelectors with withState. This ensures that the outer function that connect sees will have only one defined argument. This will make react-redux more efficient with its cache in situations where your selectors do not ever use ownProps.

import { combineSelectors, withState } from '@comfy/redux-selectors'

const mapStateToProps = withState(combineSelectors({
  item: 'department.produce.fruits.oranges'
}))

const state = {
  department: {
    produce: {
      fruits: {
        apples: 1,
        oranges: 2
      }
    }
  }
}

mapStateToProps(state) // => { item: 2 }

Configuring combineSelectors with withProps

When you need to configure a selector based on ownProps, you can use withProps. This is useful for times when you want to use configuration from ownProps to create your selectors, for instance, if you are using a configurable selector created by withOptions. Below you can see that the fruit selector will change based on the props that are passed.

import { combineSelectors, withProps } from '@comfy/redux-selectors'

const mapStateToProps = withProps(props => combineSelectors({
  item: `department.produce.fruits.${props.type}`
}))

const state = {
  department: {
    produce: {
      fruits: {
        apples: 1,
        oranges: 2
      }
    }
  }
}
const ownProps = { type: 'oranges' }

mapStateToProps(state, ownProps) // => { item: 2 }

results matching ""

    powered by

    No results matching ""