It has a parent-child relationship. In the RTK slice, it looks like this:
application
-> personList (array of person objects)
–> assetList (array of asset objects)
Example JSON:
{
application: {
personList: [
{
id,
fname,
lname,
personFormStatus: { isValid, isDirty},
assetFormStatus: { isValid, isDirty},
assetList: [
{
type,
subtype,
amount,
}
]
}
]
}
}
And then I have 2 components, 1 per fieldgroup:
const PersonFormComponent = () => {}
const AssetFormComponent = () => {}
I have created a selector in the appSlice.tsx:
export const selectPeopleUniqueIdAndAssetFormStatus = createSelector(
(state) => {
console.log('inside inputSelectors');
return state.application.personList;
},
(personList) => {
console.log('inside combiner');
return personList.map((p) => ({
assetFormStatus: p.assetFormStatus,
id: p.id,
}));
}
);
Inside the AssetFormCompnent which doesn’t memoize, it keeps recalculating (even though the updates are in the Person names in the PersonFormComponent):
const AssetFormComponent = () => {
const peopleIdsAndFormStatus = useSelector(
selectPeopleUniqueIsAndAssetFormStatus
);
}
But if I pass equalityFn in AssetFormCompnent then it does memoize (even though the updates are in the Person names in the PersonFormComponent):
const AssetFormComponent = () => {
const peopleIdsAndFormStatus = useSelector(
selectPeopleUniqueIsAndAssetFormStatus, (oldv,newv) => _.isEqual(oldv,newv)
);
}
Can you please let me know if this is appropriate to use deepEquality, because I would have thought the createSelector is memoizing it already?
2
Answers
Your code doesn’t appear to be correct, your
selectPeopleUniqueIdAndAssetFormStatus
selector function isn’t being called. I’m pretty sure yourselectPeopleUniqueIsAndAssetFormStatus
selector function is correctly memoizing its value, but the problem is the anonymous selector function the UI is using. Since an array is returned the shallow equality function is necessary to get theuseSelector
hook to work like you are expecting. In fact you don’t need the anonymous selector function,selectPeopleUniqueIsAndAssetFormStatus
already expects to consume the Redux state as an argument.I suspect you are actually doing something like this:
But this is unnecessary, pass
selectPeopleUniqueIsAndAssetFormStatus
directly as the selector function:Doc for Deriving Data with Selectors describes your issue when using an array and
map
:First suggested solution in doc is to use
proxy-memoize
Documentation lists other alternatives as well.