I have a selector:
const someSelector = createSelector(
getUserIdsSelector,
(ids) => ids.map((id) => yetAnotherSelector(store, id),
);
A problem we faced when using reselect is that there is no support for dynamic dependency tracking. A selector needs to declare upfront which parts of the state will cause a recomputation.
For example, I have a list of online user IDs, and a mapping of users:
{
onlineUserIds: [ 'alice', 'dave' ],
notifications: [ /* unrelated data */ ]
users: {
alice: { name: 'Alice' },
bob: { name: 'Bob' },
charlie: { name: 'Charlie' },
dave: { name: 'Dave' },
eve: { name: 'Eve' }
}
}
I want to select a list of online users, e.g. [ { name: 'Alice' }, { name: 'Dave' } ].
Since I cannot know upfront which users will be online, I need to declare a dependency on the whole state.users branch of the store:
This works, but this means that changes to unrelated users (bob, charlie, eve) will cause the selector to be recomputed.
I believe this is a problem in reselect’s fundamental design choice: dependencies between selectors are static. (In contrast, Knockout, Vue and MobX do support dynamic dependencies.)
We faced the same problem and we came up with @taskworld.com/rereselect. Instead of declaring dependencies upfront and statically, dependencies are collected just-in-time and dynamically during each computation:
This allows our selectors to have a more fine-grained control of which part of state can cause a selector to be recomputed.