

store는 javascirpt 환경과 동일하게 작성하고, state와 dispatch 타입을 store에서 추론해서 export 한다.
RootState와 AppDispatch는 Hooks에서 사용될 Dispatch와 Selector에서 사용할 타입이다.
// store.tsx
import { configureStore } from "@reduxjs/toolkit";
import loadingSlice from "../slice/loading";
const store = configureStore({
reducer: {
loadingReducer: loadingSlice.reducer,
},
});
// state 타입 추론
export type RootState = ReturnType<typeof store.getState>;
// dispatch 타입 추론
export type AppDispatch = typeof store.dispatch;
export default store;
useSelector는 컴포넌트에서 데이터를 불러오기 위해 사용하고, useDisPatch는 action을 dispatch하기 위해 사용한다.
RootState와 AppDispatch 타입을 각 컴포넌트에서 import해서 사용할 수도 있지만 이런 타입화 과정을 모든 컴포넌트에 적용하는 것보다 hooks.tsx라는 별도의 파일을 만들어 pre-typed된 버전을 만들어주는 것이 편하다.
import { useDispatch, useSelector } from "react-redux";
import type { TypedUseSelectorHook } from "react-redux";
import type { RootState, AppDispatch } from "../store/store";
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
const x : (a:number) => string = (x) => String(x)
const x : (a:number) => string
const loadingState = useSelector((state : RootState) => state.loadingReducer.isLoading);
const loadingState = useAppSelector((state) => state.loadingReducer.isLoading);
import { createSlice } from "@reduxjs/toolkit";
interface LoadingState {
isLoading: boolean;
}
const initialLoadingState: LoadingState = { isLoading: true };
const loadingSlice = createSlice({
name: "loading",
initialState: initialLoadingState,
reducers: {
fulfilled(state) {
state.isLoading = false;
},
pending(state) {
state.isLoading = true;
},
},
});
export const { fulfilled, pending } = loadingSlice.actions;
export default loadingSlice;
PayloadAction<T> 타입을 사용해야한다. 여기서 사용된 제네릭 타입은 action.payload 인자로 사용된다.increaseByFive(state, action: PayloadAction < number >) {
state.countNum = state.countNum + action.payload;
},
useAppSelector, useAppDispatch을 import 한다.import { fulfilled, pending } from "../../redux/slice/loading";
import { useAppDispatch, useAppSelector } from "../../redux/hooks/hooks";
const dispatch = useAppDispatch();
const loadingState = useAppSelector((state) => state.loadingReducer.isLoading);
const getDiaryData = async () => {
try {
const res = await BASE_API.get(`/diary`);
dispatch(fulfilled()); // 요청이 성공하면 loading을 false로 바꿈
setDiaryData(res.data);
} catch (err) {
dispatch(pending()); // 요청이 실패하면 loading을 true로 바꿈
console.error(err);
}
};
useEffect(() => {
getDiaryData();
}, []);