Trying to use createSelector with RTK Query
export const selectXX = createSelector(
[
(state: IRootState) => state.xx.A
(state: IRootState) => state.xx.B,
],
(A, B):IViewerSpace[] => {
if (A == null || B == null) {
return [];
}
const args = {
A: A,
B: B
}
const resp = designRTK.endpoints.getData.select(args);
const abc = resp(state).data // state not available
...some transformationlogic
});
To fetch data I’m using endpoints.getData.select(args)
To access the data
const abc = resp(state).data
// state not available
Problem is, the full state is not available when using createSelector.
How do I solve this?
Something like this may work:
export const selectXX = createSelector(
[
(state: IRootState) => state.xx.A
(state: IRootState) => state.xx.B,
(state: IRootState) => state, // <-- add input selector that returns entire state
],
(A, B, state): IViewerSpace[] => {
if (A == null || B == null) {
return [];
}
const args = { A, B };
const { data } = designRTK.endpoints.getData.select(args)(state);
// ...some transformationlogic
}
);
But using a selector function that just returns its input or just returns the entire state object could have negative effects and is not generally recommended. This implementation will likely re-run anytime the Redux state is updated.
There’s a dependency on the selected/derived A and B state.
I suggest splitting up the logic to make the returned “A or B” selector value an additional argument passed to a second selector, the UI will need to call both.
Example:
const selectXX = (state: IRootState) => state.xx;
const selectXXA = createSelector(
[selectXX],
xx => xx.A,
);
const selectXXB = createSelector(
[selectXX],
xx => xx.B,
);
export const selectAandB = createSelector(
[
selectXXA,
selectXXB,
],
(A, B): IViewerSpace[] => ({ A, B }),
);
In the UI:
const aAndB = useSelector(selectAandB);
const selectXX = useMemo(() => designRTK.endpoints.getData.select(aAndB), [aAndB]);
const value = useSelector((state: IRootState) => {
const { data } = selectXX(state);
// ...some transformationlogic
});
4