Reselect Utils
Edit page
IntroductionQuick StartPath SelectorChain Selector
Guides
Graphs
API

Quick Start

Path Selector

Suppose you have such a normalized state:

const state = {
persons: {
1: {
id: 1,
firstName: 'Marry',
secondName: 'Poppins',
},
2: {
id: 2,
firstName: 'Harry',
secondName: 'Potter',
},
},
};

And you want to build something like this selector:

const personFullNameSelector = createSelector(
(state, props) => state.persons[props.personId].firstName,
(state, props) => state.persons[props.personId].secondName,
(firstName, secondName) => `${firstName} ${secondName}`,
);

As you can see in the dependencies of this selector quite a lot of boilerplate code. The problem of duplicate code can be solved with createPathSelector:

import { createPathSelector } from 'reselect-utils';
const personSelector = (state, props) => state.persons[props.personId];
const personFullNameSelector = createSelector(
createPathSelector(personSelector).firstName(),
createPathSelector(personSelector).secondName(),
(firstName, secondName) => `${firstName} ${secondName}`,
);

You can also add default values if you want the selector to produce an adequate result even in the absence of the necessary person in the state:

import { createPathSelector } from 'reselect-utils';
const personFullNameSelector = createSelector(
createPathSelector(personSelector).firstName('John'),
createPathSelector(personSelector).secondName('Doe'),
(firstName, secondName) => `${firstName} ${secondName}`,
);

There are short aliases for many helpers in this library, so you can re-write your code like this:

import { path } from 'reselect-utils';
const personFullNameSelector = createSelector(
path(personSelector).firstName('John'),
path(personSelector).secondName('Doe'),
(firstName, secondName) => `${firstName} ${secondName}`,
);

You can also work with objects of unlimited nesting:

import { path } from 'reselect-utils';
const personSelectorInfo = createSelector(
path(personSelector).address.street('-'),
path(personSelector).some.very.deep.field(123),
(street, field) => ({ street, field }),
);

A more detailed description can be found here.

Chain Selector

Suppose you have such a normalized state:

const state = {
persons: {
1: {
id: 1,
firstName: 'Marry',
secondName: 'Poppins',
},
2: {
id: 2,
firstName: 'Harry',
secondName: 'Potter',
},
},
messages: {
100: {
id: 100,
personId: 1,
text: 'Hello',
},
200: {
id: 200,
personId: 2,
text: 'Buy',
},
},
};

And you want to select a person by the message id. You can write something like this:

const personSelectorByMessageId = (state, props) => {
const message = state.messages[props.messageId];
return state.persons[message.personId];
};

This is an acceptable solution, but what if the chain is longer? Chain Selector will help to solve such problems:

import { chain, bound } from 'reselect-utils';
const messageSelector = (state, props) => state.messages[props.messageId];
const personSelector = (state, props) => state.persons[props.personId];
const personByMessageIdSelector = chain(messageSelector)
.chain((message) => bound(personSelector, { personId: message.personId }))
.build();

Chain Selector allows you to create dynamic selectors that depend on the current state. Moreover, the callback that is passed to the chain method is cached by input parameters. bound binds the selector to specific parameter values and turns a parametric selector into an non parametric. And at the end you must call the build method to get the normal selector. It’s like a chain of Promises. Chain Selector and Bound Selector are described in detail in Guides section.