Previously I wrote , this story will cover other details of its use. about RTK Imagine we need to display the same kind of data but from different resources depending on the incoming parameter value. In this case, we will have the component with two hooks that handle requests and receive data. Basically, the representation of API looks like this: export const configApi = baseApi.injectEndpoints({ endpoints: build => ({ fetchConfigDetails: build.query<IConfig[], IBaseRequest>({ query: arg => `/config-details`, transformResponse: (x: IResponse<IConfig[]>) => x.result, providesTags: ['ConfigDetails'], }), fetchConfigRunDetails: build.query<IConfig[], IRunRequest>({ query: arg => `/${arg.id}/config-details`, transformResponse: (x: IResponse<IConfig[]>) => x.result, providesTags: ['ConfigRunDetails'], }), }), overrideExisting: true, }); It has two endpoints and the main difference between them is the argument ‘id’, so actually the resources are different. So the cache will be also different, one for and one for . ConfigDetails ConfigRunDetails For the clarification on where hooks take their names, I will provide the next example: export const { useFetchConfigDetailsQuery, useFetchConfigRunDetailsQuery, } = configApi; The hook name consists of the prefix ‘use’, the endpoint name , and the postfix of the request’s type (a function that is used to create the endpoint) ‘build.query’ → . fetchConfigDetails useFetchConfigDetailsQuery And these two hooks will be used in one component: const RowResultsDetails: React.FC<IProps> = () => { const { id } = useParams<IRouteParams>(); const fetchDetails = useFetchConfigDetailsQuery( { }, { skip: !!id, selectFromResult: ({ data, isFetching }) => ({ isFetching: isFetching, data: selectConfigDetails(data), }), } ); const fetchRunDetails = useFetchConfigRunDetailsQuery( { id }, { skip: !id, selectFromResult: ({ data, isFetching }) => ({ isFetching: isFetching, data: selectRunConfigDetails(data), }), } ); const { data, isFetching } = id ? fetchRunDetails : fetchDetails; return ( <div> <Section.Title>({data.length})</Section.Title> ... </div> ); } As you may know, hooks in React must have the same order and can’t be inside some ‘if else’ condition. In RTK because of such constraint, there is a special property ‘skip’ direct in the hook second parameter (options). With this option, you can tell RTK to execute or not execute the hook. Additionally, for render optimization, RTK provides the possibility to use reselect library to choose the data that you need in this particular component. In other words, and are selectors to memoize data from the cache. If the request will be invoked and selected data is not changed, nothing will happen in the component. selectConfigDetails selectRunConfigDetails The selector actually has no difference from the store selector except you don’t provide the state to it. const emptyArray = []; export const selectConfigDetails = createSelector( [ (data?: IConfig[]) => data ], (data) => data?.filter(c => c.isAvailable) ?? emptyArray ); An important point here is if you are using the same selector for both hooks it will cause redundant rerender. In other words ‘selector’ is unique and remembers the result. For the same selector, there will be two different values in the result. to not rerender the component frequently. As well if you prefer to use the hook to memoize data, in this scenario there needs to be two different usages. Be careful useMemo useMemo