TypeScript를 사용해서 기존에 만들어놨던 TodoList를 리팩토링 하려고 한다.
redux-toolkit을 사용했으며, persist도 사용했다.
useAppSelector
const count = useSelector((state: RootState) => state.counter.value)
useSelector를 사용하면, useSelector를 사용하는 모든 곳의 state에 위 코드처럼 타입을 지정해줘야한다.
const count = useAppSelector((state) => state.counter.value)
하지만 타입을 미리 지정해주면 타입을 지정해줄 필요가 없다. (타입 추론 굿)
// configStore.ts
import { combineReducers, configureStore } from '@reduxjs/toolkit';
import storage from 'redux-persist/lib/storage';
import { persistReducer } from 'redux-persist';
import thunk from 'redux-thunk';
import todoReducer from '../modules/todo';
const persistConfig = {
key: 'root',
storage,
};
const rootReducer = combineReducers({
todoReducer,
});
const postPersistedReducer = persistReducer(persistConfig, todoReducer);
const store = configureStore({
reducer: {
todoReducer: postPersistedReducer,
},
middleware: [thunk], // thunk 사용할 때
});
export default store;
// React에서 사용할 수 있도록 타입을 만들어 export 해준다.
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof rootReducer>; // todoReducer: {todos: []}
// ReturnType은 <>속의 반환 타입으로 구성된 타입을 생성한다.
ReturnType은 <>속의 반환 타입으로 구성된 타입을 생성한다.
function fn(): { a: number; b: string };
type Type1 = ReturnType<() => string>;
// type Type1 = string
type Type2 = ReturnType<(s: string) => void>;
// type Type2 = void
type Type3 = ReturnType<<T>() => T>;
// type Type3 = unknown
type Type4 = ReturnType<<T extends U, U extends number[]>() => T>;
// type Type4 = number[]
type Type5 = ReturnType<typeof f1>;
/*
type Type5 = {
a: number;
b: string;
}
*/
type Type6 = ReturnType<any>;
//type Type6 = any
type Type7 = ReturnType<never>;
//type Type7 = never
// hooks.ts
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { AppDispatch, RootState } from './redux/config/configStore';
// 일반적인 "useDispatch"와 "useSelector" 대신 앱 전체에서 사용하십시오
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
useSelector를 할당하고 TypedUseSelectorHook에 Generic Type을 받는 것 부분은 아래 예시를 보면 이해하는데 도움이 된다.
import { TypedUseSelectorHook, useSelector } from 'react-redux';
interface TypedUseSelectorHook<T> {
name: T;
}
interface RootState {
state: {
text: string,
isDone: boolean,
}
}
const useAppselector: TypedUseSelectorHook<RootState> = {name: {
state: {
text: 'a!',
isDone: false,
}
}}
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
그리고 아래처럼 사용하면 된다.
const globalTodo = useAppSelector((state) => state.todoReducer.todos);