This lesson covers two important principles. The first is memoized selectors with createSelector and RTK Query's built-in endpoint selectors.
RTK Query doesn't give you an easy way to access its cache manually but it does give you these enpoint selector helpers that allow you to reach into the cache when you need it.
Using these memoized endpoint selectors are recommended because they only calculate a new value any time the data arguments change while the previous selectors we had would be re-run on every re-render.
While not mentioned in the lesson you don't need to use endpoint selectors with createSelector. This would work perfectly fine:
export const getServicesForLuckyDog = (state) => {
const { data: dogs } = api.endpoints.getDogs.select()(state);
const { data: services } = api.endpoints.getServices.select()(state);
// if you don't have a lucky dog, show all of the services
const dog = dogs?.[state.dogs.luckyDog];
if (!dog) {
return services;
}
// ...
};
Jamund Ferguson: [0:00] Inside of servicesSlice.js, import { createSelector } from "@reduxjs/toolkit". Then, at the bottom of the file where we have our getServicesForLuckyDog selector, let's go ahead and add a new line right above that that says export const getServicesForLuckyDog = createSelector.
[0:18] Then, we're going to say, api.endpoints.getServices.select. Below that, api.endpoints.getDogs.select. Lastly, we're going to have an arrow function that takes in state and returns state.dogs.luckyDog.
[0:38] For our final function, the one that ties all these pieces of state together, we're going to take in our servicesResponse, the dogsResponse, and lastly, the luckyDog. With that, we can start to copy over the contents of our existing selector function. Instead of const dog equals myDogs?. [state.dogs.luckyDog] , we can access access luckyDog directly because that comes as the third argument.
[1:03] To get myDogs here, we need to destructure that off the data param of dogsResponse. It will be { data: myDogs } and we'll keep the null sinc operator in there. To get services, we'll do the same thing with the servicesResponse, { data: services }.
[1:20] With that, we can remove our handwritten selector. It's telling us we don't have api imported. Let's go ahead and import { api } from "../../store/apiSlice". Now, we have a fully memoized selector that relies on api.endpoints.select to get access to the data from within the RTK Query cache. What this means for us is back on the services page, instead of passing in services and myDogs here, we only need to pass in state.
[1:50] RTK Query doesn't give us an easy way to access the cache from Redux manually but does give us these great helper methods that make it really easy to reach into the cache when we need it. Memoize selectors like this one are recommended because they only calculate a new value. Anytime the data arguments change, the previous selector we had written would get rerun on every single render.