createStructuredSelector
A convenience function that simplifies returning an object made up of selector results.
Parameters
Name | Description |
---|---|
inputSelectorsObject | A key value pair consisting of input selectors. |
selectorCreator? | A custom selector creator function. It defaults to createSelector . |
Returns
A memoized structured selector.
Type Parameters
Name | Description |
---|---|
InputSelectorsObject | The shape of the input selectors object. |
MemoizeFunction | The type of the memoize function that is used to create the structured selector. It defaults to lruMemoize . |
ArgsMemoizeFunction | The type of the of the memoize function that is used to memoize the arguments passed into the generated structured selector. It defaults to lruMemoize . |
Examples
Modern Use Case
- TypeScript
- JavaScript
createStructuredSelector/modernUseCase.ts
import { createSelector, createStructuredSelector } from 'reselect'
export interface RootState {
todos: {
id: number
completed: boolean
title: string
description: string
}[]
alerts: { id: number; read: boolean }[]
}
// This:
export const structuredSelector = createStructuredSelector(
{
todos: (state: RootState) => state.todos,
alerts: (state: RootState) => state.alerts,
todoById: (state: RootState, id: number) => state.todos[id]
},
createSelector
)
// Is essentially the same as this:
export const selector = createSelector(
[
(state: RootState) => state.todos,
(state: RootState) => state.alerts,
(state: RootState, id: number) => state.todos[id]
],
(todos, alerts, todoById) => {
return {
todos,
alerts,
todoById
}
}
)
createStructuredSelector/modernUseCase.js
import { createSelector, createStructuredSelector } from 'reselect'
// This:
export const structuredSelector = createStructuredSelector(
{
todos: state => state.todos,
alerts: state => state.alerts,
todoById: (state, id) => state.todos[id]
},
createSelector
)
// Is essentially the same as this:
export const selector = createSelector(
[state => state.todos, state => state.alerts, (state, id) => state.todos[id]],
(todos, alerts, todoById) => {
return {
todos,
alerts,
todoById
}
}
)
In your component:
- TypeScript
- JavaScript
createStructuredSelector/MyComponent.tsx
import type { RootState } from 'createStructuredSelector/modernUseCase'
import { structuredSelector } from 'createStructuredSelector/modernUseCase'
import type { FC } from 'react'
import { useSelector } from 'react-redux'
interface Props {
id: number
}
const MyComponent: FC<Props> = ({ id }) => {
const { todos, alerts, todoById } = useSelector((state: RootState) =>
structuredSelector(state, id)
)
return (
<div>
Next to do is:
<h2>{todoById.title}</h2>
<p>Description: {todoById.description}</p>
<ul>
<h3>All other to dos:</h3>
{todos.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
</div>
)
}
createStructuredSelector/MyComponent.jsx
import { structuredSelector } from 'createStructuredSelector/modernUseCase'
import { useSelector } from 'react-redux'
const MyComponent = ({ id }) => {
const { todos, alerts, todoById } = useSelector(state =>
structuredSelector(state, id)
)
return (
<div>
Next to do is:
<h2>{todoById.title}</h2>
<p>Description: {todoById.description}</p>
<ul>
<h3>All other to dos:</h3>
{todos.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
</div>
)
}
Simple Use Case
const selectA = state => state.a
const selectB = state => state.b
// The result function in the following selector
// is simply building an object from the input selectors
const structuredSelector = createSelector(selectA, selectB, (a, b) => ({
a,
b
}))
const result = structuredSelector({ a: 1, b: 2 }) // will produce { x: 1, y: 2 }
createStructuredSelector
takes an object whose properties are input selectors and returns a structured selector. The structured selector returns an object with the same keys as the inputSelectorsObject
argument, but with the selectors replaced with their values.
const selectA = state => state.a
const selectB = state => state.b
const structuredSelector = createStructuredSelector({
x: selectA,
y: selectB
})
const result = structuredSelector({ a: 1, b: 2 }) // will produce { x: 1, y: 2 }
Structured selectors can be nested:
const nestedSelector = createStructuredSelector({
subA: createStructuredSelector({
selectorA,
selectorB
}),
subB: createStructuredSelector({
selectorC,
selectorD
})
})
Defining a Pre-Typed createStructuredSelector
As of Reselect 5.1.0, you can create a "pre-typed" version of createStructuredSelector
where the state
type is predefined. This allows you to set the state
type once, eliminating the need to specify it with every createStructuredSelector
call.
To do this, you can call createStructuredSelector.withTypes<StateType>()
:
- TypeScript
- JavaScript
createStructuredSelector/withTypes.ts
import { createStructuredSelector } from 'reselect'
export interface RootState {
todos: { id: number; completed: boolean }[]
alerts: { id: number; read: boolean }[]
}
export const createStructuredAppSelector =
createStructuredSelector.withTypes<RootState>()
const structuredAppSelector = createStructuredAppSelector({
// Type of `state` is set to `RootState`, no need to manually set the type
todos: state => state.todos,
alerts: state => state.alerts,
todoById: (state, id: number) => state.todos[id]
})
createStructuredSelector/withTypes.js
import { createStructuredSelector } from 'reselect'
export const createStructuredAppSelector = createStructuredSelector.withTypes()
const structuredAppSelector = createStructuredAppSelector({
// Type of `state` is set to `RootState`, no need to manually set the type
todos: state => state.todos,
alerts: state => state.alerts,
todoById: (state, id) => state.todos[id]
})