createSelector
was brought in to RTK from the popular reselect library. While it's not needed to create selector functions, it makes it a lot easier to create efficient selectors that avoid doing more work than needed.
createSelector
takes two types of arguments. There are inputSelectors
(and there can be more than one of these) and then there's the resultFunction
. You pass in these input selectors and then the result function processes the data that gets returned. As long as the input values don't change, the generated selector won't re-run the result function.
If the data you're working with isn't large or the calculations aren't complex, you don't really need to use createSelector
. But it's a good tool to have in your toolbox.
Check out this link for more info: https://github.com/reduxjs/reselect#createselectorinputselectors--inputselectors-resultfunc
Jamund Ferguson: [0:00] Open up cartSlice.ts in your IDE, and in the getNumItems function, type console.log calling numItems. If you go back into your browser and open up your console, you'll see calling numItems listed here.
[0:13] Each time I click add at the cart, it adds an additional instance of that in our logs, which makes sense because the number of items changed. When we switch tabs back and forth from products to something else, we notice it also changes. Our selector is getting called more than it needs to.
[0:29] It only really needs to update any time items changes, but it's being called anytime anything in our Redux Store changes. Back in cartSlice, let's import createSelector from the Redux Toolkit. Below our get numItems function, type export const getMemoizedNumItems = createSelector.
[0:50] That's going to take in two functions. The first one looks like a standard selector. State, which is of type RootState. That's going to return state.cart.items.
[1:00] For the second function, let's take items. Let's do something with them. We're going to convert them into the number of items. We'll say let numItems = , return numItems. In between, we'll say for (let id in items), numItems += items [id] . It's basically the same as we had in our getNumbItems function, except it's running on the items object instead of the entire state.
[1:24] Now, let's add up here calling getMemoizedNumItems. Back in CartLink.tsx, let's pull in getMemoizedItems from cartSlice. Let's use that instead of getNumItems for our selector. Back in our IDE, calling getMemoizedNumItems gets called once. If I add things to the cart, it also gets updated. If I switch tabs, it doesn't change.
[1:48] That's because the createSelector function will remember the value of its final selector as long as the first one hasn't changed. It's going to run this one every single time. All that does is a simple check to make sure that the items hasn't changed. If that value hasn't changed, it's not going to bother rerunning our more computationally intensive selector here.
[2:07] In this case, it's not going to make any difference at all. For users, there are definitely cases where you're processing a fair amount of data in a selector. You want to make sure to memorize it so that it doesn't get run more often than it needs to.