redux-bind-selectors
v1.1.13
Published
A Redux store enhancer for computing derived state by binding selectors to the store
Downloads
4,446
Maintainers
Readme
redux-bind-selectors
A Redux store enhancer for computing derived state by binding selectors to a Redux store, so that getState()
incorporates derived data.
import { createStore } from 'redux'
import bindSelectors from 'redux-bind-selectors'
const store = createStore(
myReducer, // The Redux reducer
{ numbers: [4, 6, 9, 2] }, // Initial state (optional)
bindSelectors({ total }) // Bind the `total` selector
)
store.getState()
// {
// numbers: [4, 6, 9, 2], // <-- initial state from the store
// total: 21 // <-- result of the `total` selector
// }
Installation
npm install --save redux-bind-selectors
Usage
bindSelectors()
takes an object where the keys are paths in the state object, and the properties are selector functions. This is analogous to the Redux combineSelectors()
function.
const enhancer = bindSelectors({
selector1: myReselectSelector,
selector2: state => state.a + state.b
})
Selectors are pure functions that take the state object as their only argument. Check out reselect to build efficient selectors.
When creating the store, the enhancer should be the last argument to the createStore()
function. If you have more than one enhancer, you can use the compose()
function in Redux to compose them.
const store1 = createStore(reducer, enhancer)
const store2 = createStore(reducer, initialState, enhancer)
Motivation
A Redux store should contain the minimum representation of state, so rather than storing:
{
numbers: [4, 6, 9, 2],
total: 21 // <-- this can be calculated from `numbers`
}
it should just store:
{
numbers: [4, 6, 9, 2]
}
and calculate total
when needed with a selector:
const total = state => state.numbers.reduce((sum, value) => sum + value, 0)
(Pro tip: reselect would be more efficient)
But...
Instead of a single, simple state object, state is now split between the store and a collection of selector functions, which adds complexity.
Solution without redux-bind-selectors
Use mapStateToProps()
in React Redux, to connect the selectors to the state.
Solution with redux-bind-selectors
Use this module to bind the selectors to the store, so that the store runs the selectors for you, producing a single object. This approach retains the advantages of minimum state representation, and separation of concerns between reducers and selectors.
Which one should I use?
If you are new to React and Redux, then you should initially consider mapStateToProps()
, as recommended by the Redux documentation.
You should try out this module if you are not using React, you prefer to keep view and model logic separate, you live on the edge, or you consider this approach to be more elegant. It's relatively easy to switch between the two, or do both at the same time.
If the output of getState()
is used for other purposes (for instance, to persist the state), then careful consideration should be given as to how this module will affect that.
Notes
- A selector cannot have the same path in the state object as a reducer. (This is why we do not simply reuse the
createStructuredSelector()
function from reselect) - Paths are all top level object keys
- A selector cannot return
undefined
, in order to be consistent with Redux where a combined reducer cannot returnundefined
. Instead, usenull
.
License
See LICENSE.md
Contributing
See CONTRIBUTING.md