What are Redux selectors? Why use them?
Selectors are functions that take Redux state as an argument and return some data to pass to the component.
They can be as simple as:
const getDataType = state => state.editor.dataType;
Or they can do more complicated data transformations like filter a list.
They are typically used in mapStateToProps
1 in react-redux
's connect
:
For example this
export default connect(
(state) => ({
dataType: state.editor.dataType,
})
)(MyComponent);
becomes this:
export default connect(
(state) => ({
dataType: getDataType(state),
})
)(MyComponent);
Why?¶
One reason is to avoid duplicated data in Redux.
Redux state can be thought of like a database and selectors like SELECT queries to get useful data from the database. A good example is a filtered list.
If we have a list of items in Redux but want to show a filtered list of the items in the UI, we could filter the list, store it in Redux then pass it to the component. The problem is there are two copies of some of the items and it is easier for data to get out of sync. If we wanted to update an item, we'd have to update it in two places.
With selectors, a filterBy
value would be stored in Redux and a selector would be used to compute the filtered list from the Redux state.
Why not perform the data transformations in the component? ¶
Performing data transformations in the component makes them more coupled to the Redux state and less generic/reusable. Also, as Dan Abramov points out, it makes sense to keep selectors near reducers because they operate on the same state. If the state schema changes, it is easier to update the selectors than to update the components.
Performance¶
mapStateToProps
gets called a lot so performing expensive calculations there is not good. This is where the reselect
library comes in. Selectors created with reselects
's createSelector
will memoize to avoid unnecessary recalculations. Note if performance is not an issue, createSelector
is not needed.
Update: in my experience, even more important than memoizing expensive calcuations in selectors is preserving referential equality of values returned by selectors that are passed as props to memo
-wrapped function components or PureComponent
derived class components to prevent re-rendering. See my post on React perfomance for more information.
References / See also¶
- I got interested in selectors after watching Dan Abramov's video: https://egghead.io/lessons/javascript-redux-colocating-selectors-with-reducers
- Redux docs on selectors: http://redux.js.org/docs/recipes/ComputingDerivedData.html
- Reselect: https://github.com/reactjs/reselect
1. mapStateToProps
can be considered a selector itself
Related posts
- How to use ast-grep with GraphQL — posted 2024-09-24
- Next.js App Router (RSC) projects w/ open source code — posted 2024-07-30
- Next.js Relay GraphQL Pokemon example — posted 2024-05-22
- Example Node.js Passport.js SAML app using OneLogin — posted 2024-05-10
- Aphrodite to CSS Modules codemod — posted 2022-12-09
- Simple codemod example with jscodeshift — posted 2021-05-03