The useSelector hook from react-redux is incredibly easy to use, but doesn't work super well with TypeScript. The useAppSelector
function we created in the last lesson solves this by telling it that state
is always going to be of the RootState
type we created.
const products = useAppSelector((state) => state.products.products);
This only works with function components. Class components cannot use hooks and need to use the legacy connect higher order component to gain access to data in the redux store.
Once we type the useAppSelector
method and our individual slices we don't need any special type syntax as its all covered by the RootState
type we defined earlier.
Anytime the redux store changes, the selector function passed in to useAppSelector
will be executed. If the value returned is not an exact match to the last returned value, redux will force the component to re-render.
useSelector/useAppSelector
can also take a second argument, an equality function. Using _.isEqual
from Lodash for example could help prevent additional renders in some cases. react-redux
also includes a shallowEqual
method that will compare all of the key/value pairs of an object one layer deep. That works well if your selector return an object made up of strings, numbers or booleans.
import { shallowEqual, useSelector } from 'react-redux'
const selectedData = useSelector(selectorReturningObject, shallowEqual)
Jamund Ferguson: [0:00] The Products page in our application is made up of data dynamically loaded from a JSON file. That call happens inside of Products.tsx inside of this useEffect hook, which calls getProducts and then sets them into local component state. We're going to comment out this code and pull the products data from Redux instead.
[0:17] At the top of the file import { useAppSelector } from "../../app/hooks". Then, down in our component, type const products = useAppSelector. Let's pass in an arrow function which takes in the state and let's let TypeScript complete the rest. We type state, we select products, and we want products. We can see here also that because we use useAppSelector, our products list is typed properly.
[0:45] Because we store products in Redux as an object and not an array, we have to update how we map over this. We can simply type Object.values to convert that object into an array of products. With that in place if we go back to the Products page, you'll see an empty screen.
[1:02] We can test that it's working by going into productsSlice and in our initial state adding one fake product. We'll give it an id of 123 and a name of "fake product". We'll save that. You'll notice TypeScript is mad because it's missing a few values, but it's good enough to power a fake product on our page.