-
Redux Toolkit, Redux Saga와 TypeScriptWeb Dev/3. React 관련 2021. 6. 1. 15:15728x90
Redux를 통해서 상태관리를 하면 좋은데, 여전히 코드가 너무 많지 않은가 싶어서 써본 Redux Toolkit은 정말 편하긴하다.
Redux Saga와 TypeScript랑 같이써서 간단하게 API를 쏘고 응답을 받아서 처리하는 것을 해보면서 참고한 자료를 정리해두려고 한다.
전체적인 흐름은, 우선 Store에서 Thunk를 안쓸거라(toolkit은 Thunk를 기본으로 제공), 걔를 꺼줘야한다.
1. Thunk 끄기
import { configureStore, Action, getDefaultMiddleware } from "@reduxjs/toolkit"; import userSlice from "./userSlice"; import createSagaMiddleware from "redux-saga"; import { watcherSaga } from "./sagas/rootSaga"; const sagaMiddleware = createSagaMiddleware(); export const store = configureStore({ reducer: { user: userSlice, }, middleware: [...getDefaultMiddleware({ thunk: false }), sagaMiddleware], }); sagaMiddleware.run(watcherSaga); export type AppDispatch = typeof store.dispatch; export type RootState = ReturnType<typeof store.getState>;
2. UseDispatch, UseSelector가 타입추론을 할 수 있도록 살짝 바꿔주기.
hooks.ts파일을 만들어서 여기서 useDispatch, useSelector에 타입을 넣어놓고 걔를 갖다 쓰라구 한다.
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; import type { RootState, AppDispatch } from './store'; // Use throughout your app instead of plain `useDispatch` and `useSelector` export const useAppDispatch = () => useDispatch<AppDispatch>(); export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
3. toolkit에서 제공하는 방식대로 reducer도 써주되 saga관련해서 Type을 조금 지정은 해야한다.
만약 reducer에 들어가는 어떤 Payload가 아래의 형태라면
export interface LoginDataType { email: string; password: string; }
얘를 일단 export해서 saga쪽에서 쓸수있게 한다.
이게 Saga에서 처리하는 handler함수인데, SagaReturnType(Saga에서 제공)이라는 것과, PayloadAction(toolkit에서 제공)을 써서 간단하게 타입을 지정할 수 있다.
import { call, put, SagaReturnType } from "redux-saga/effects"; import { setToken, LoginDataType, setError } from "../../userSlice"; import { requestData } from "../requests/user"; import { PayloadAction } from "@reduxjs/toolkit"; // 이부분은 call하는 부분때문에 필요하다, call의 return Type을 지정 type LoginServiceResponse = SagaReturnType<typeof requestData>; export function* handleSetUser(action: PayloadAction<LoginDataType>) { try { const response: LoginServiceResponse = yield call( requestData, action.payload ); const { data } = response; yield put(setData({ ...data })); } catch (error) { console.log(error.message); yield put(setError({ error_message: error.message })); } }
- payloadAction을 통해서 들어오는 action의 Payload 데이터 타입을 지정한다
- SagaReturnType은 yield call이 실행되고 promise가 resolve됬을때의 응답의 타입을 지정한다.
이때 call에 넘겨준 requestData function의 응답의 type이 잘 지정이 되어있어야하는데 아래와 같이 지정할 수 있다.
import axios, { AxiosResponse } from "axios"; import { LoginDataType } from "../../userSlice"; import { API } from "../../../utils/common"; interface ResponseType { success: boolean; token: boolean; } export function requestSetUser( data: LoginRequestType ): Promise<AxiosResponse<ResponseType>> { return axios.post(`${API}/login`, data); }
이런식으로 function의 반환값의 타입을 지정하면 된다.
후기
Redux랑 Saga쪽을 좀더 공부해서 상태관리에 더 자신이 생기면 앱 개발이 더 재미있을 것 같다. Toolkit을 사용하더라도 기존방식으로 작성한 reducer도 여전히 잘 동작하기 때문에 나는 toolkit위주로 앱을 개발해야겠다.
Ref
- Redux Toolkit
https://www.youtube.com/watch?v=iBUJVy8phqw
- Redux Toolkit with Redux Saga
https://www.youtube.com/watch?v=2hZhIoRuua4
- 잘 설명이 된 개인 블로그
'Web Dev > 3. React 관련' 카테고리의 다른 글
Didact 키 구현 제대로 참교육 당했다. 키를 잘쓰자 (0) 2021.11.11 Chart그리는 툴 - react-chartjs-2(TypeScript관련 에러처리) (0) 2021.06.02 React 관련 싹훑기(13) Redux toolkit 문서 읽기 (0) 2021.05.31 React 관련 싹훑기(12) - React-ContentEditable관련 reference가업데이트가 안되는 문제 해결, (0) 2021.05.30 React 관련 싹훑기(11) - Reordering blocks using react-beautiful-dnd (0) 2021.05.30