Using 'createSelector' - creating Custom 'useAppSelector' : Which approch is better?

42 Views Asked by At

This is my code for cretaing Selectors

import { createSelector } from '@reduxjs/toolkit';
import { RootState } from 'Store/InjectorsTypes';
import { initialState } from 'Slice/DocumentHubSlice';

const selectDomain = (state: RootState) => state?.documentHub || initialState;

export const selectDocuments = createSelector(
  [selectDomain],
  (state) => state.documents,
);

export const selectUploadedDocuments = createSelector(
  [selectDomain],
  (state) => state.uploadedDocuments,
);

export const selectDocumentsLoading = createSelector(
  [selectDomain],
  (state) => state.documentsLoading,
);

export const selectDocumentsLoaded = createSelector(
  [selectDomain],
  (state) => state.documentsLoaded,
);

export const selectDocumentsEnded = createSelector(
  [selectDomain],
  (state) => state.documentsEnded,
);

export const selectSort = createSelector(
  [selectDomain],
  (state) => state.sort,
);

export const selectCompanyName = createSelector(
  [selectDomain],
  (state) => state.companyName,
);

export const selectCompanyLogo = createSelector(
  [selectDomain],
  (state) => state.companyLogo,
);

export const selectChatGptAllowed = createSelector(
  [selectDomain],
  (state) => state.chatgptAllowed,
);

export const selectDrawerOpen = createSelector(
  [selectDomain],
  (state) => state.drawerOpen,
);

export const selectUploading = createSelector(
  [selectDomain],
  (state) => state.uploading,
);

export const selectDownloading = createSelector(
  [selectDomain],
  (state) => state.downloading,
);

export const selectDeleting = createSelector(
  [selectDomain],
  (state) => state.deleteing,
);

export const selectDownloadUrl = createSelector(
  [selectDomain],
  (state) => state.downloadUrl,
);

However, I can see too much redundancy. I want to replace above code with my this code

import { useSelector } from 'react-redux';
import { RootState } from 'Store/InjectorsTypes';
import { initialState } from 'Slice/DocumentHubSlice';

export function useAppSelector<T>(selector: (state: RootState) => T) {
  return useSelector((state: RootState) => selector(state) || initialState);
}

With this custom hook, I can use it in my components like this

const documents = useAppSelector((state) => state.documentHub.documents);
const uploadedDocuments = useAppSelector((state) => state.documentHub.uploadedDocuments);
// ... and so on

I want to know if the second approach is better than the first. Should I replace my initial code with this second appraoch?

1

There are 1 best solutions below

0
phry On

Generally, you should always be using the useAppSelector shown in the "TypeScript quickstart" guide for Redux Toolkit, independenlty of the question if you use createSelector or not.

Apart from that, you probably don't need createSelector for any of the examples you've given, as long as those selectors don't do any meaningful (expensive) calculation or create new objects - in those two cases, you should always use memoized selectors.

But it doesn't hurt to use them either - so it's up to you.

PS: That || initialState is seriously weird - you'll always have a state there, so why add that?