How to use the useSelector Redux hook with Typescript
source link: https://typeofnan.dev/how-to-use-the-useselector-redux-hook-with-typescript/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Nick Scialli • May 17, 2021 • 🚀 3 minute read
Redux offers the useSelector hook to get values from your store. If you’re using Typescript, make sure you get the most out the hook by typing it correctly.
A basic store with user information
Let’s say you have a store that contains some information about a logged-in user. We’ll do a really basic store setup here with some action creators and a reducer.
import { createStore } from 'redux';
type User = {
name: string;
age: number;
admin: boolean;
};
const defaultUser: User = {
name: 'Guest',
age: 0,
admin: false,
};
const setName = (payload: string) =>
({
type: 'SET_NAME',
payload,
} as const);
const setAge = (payload: number) =>
({
type: 'SET_AGE',
payload,
} as const);
const setAdmin = (payload: boolean) =>
({
type: 'SET_ADMIN',
payload,
} as const);
type Actions = ReturnType<typeof setName | typeof setAge | typeof setAdmin>;
function reducer(state = defaultUser, action: Actions) {
switch (action.type) {
case 'SET_NAME':
return { ...state, name: action.payload };
case 'SET_AGE':
return { ...state, age: action.payload };
case 'SET_ADMIN':
return { ...state, admin: action.payload };
default:
return state;
}
}
const store = createStore(reducer);
type RootState = ReturnType<typeof store.getState>;
Note that I’m deducing the type of RootState
here from the return type of store.getState
, which is a bit unnecessary since our state is the same as User
, but in a more complex scenario this would be much more helpful.
Using the useSelector hook
We now want to display our user’s name in a Header
component. Without types, we can envision using the useSelector
hook like this:
import { useSelector } from 'react-redux';
export const Header = () => {
const name = useSelector((state) => state.name);
return <div>Welcome, {name}!</div>;
};
However, if we have our Typescript compiler to yell about implicit any
, then we have a compilation error here. But furthermore, we want to get the best out of Typescript, so adding some types to useSelector
to make sure we’re accessing the correct path in state and to make sure our returned value is the expected type is important to us.
To add types to useSelector
, we have to pass it two Generic
values: the first Generic is the type of our entire state object (recall we created RootState
!) and the second Generic is the type of the returned value we expect (in this case, we expect name
to be a string
).
With this in mind, here’s how we type our useSelector
hook:
import { useSelector } from 'react-redux';
export const Header = () => {
const name = useSelector<RootState, string>((state) => state.name);
return <div>Welcome, {name}!</div>;
};
Now our compiler is happy and we’re assured that we are accessing the name
property on our state correctly.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK