[졸업프로젝트] React + TypeScript로 변환 - 2

krkorklo·2022년 1월 24일
0

졸업프로젝트

목록 보기
3/7

TypeScript에서 Redux 사용

typesafe-actions 사용

redux와 비동기 함수 호출을 사용하기 위해 actionType 선언과 함수 호출 부분을 묶어줬다.

export const createRequestActionTypes = (type: string) => {
  const SUCCESS = `${type}_SUCCESS`;
  const FAILURE = `${type}_FAILURE`;
  return [type, SUCCESS, FAILURE];
};

export default function createRequestThunk(type: string, request: any) {
  const SUCCESS = `${type}_SUCCESS`;
  const FAILURE = `${type}_FAILURE`;

  return (params: any) => async (dispatch: any) => {
    dispatch({ type });
    try {
      const response = await request(params);
      dispatch({
        type: SUCCESS,
        payload: response.data.data,
      });
    } catch (e) {
      dispatch({
        type: FAILURE,
        payload: e,
        error: true,
      });
      throw e;
    }
  };
}

params랑 request랑 dispatch는 일단 any로 놔둠
언젠가 고치겠지

// modules/media.ts
...
const [LOAD, LOAD_SUCCESS, LOAD_FAILURE] =
  createRequestActionTypes("media/LOAD");
const [UPLOAD, UPLOAD_SUCCESS, UPLOAD_FAILURE] =
  createRequestActionTypes("media/UPLOAD");

export const load = createRequestThunk(LOAD, mediaAPI.load);
export const upload = createRequestThunk(UPLOAD, mediaAPI.upload);

interface MediaType {
  id: number;
  src: string;
  videoName: string;
  videoUrl: string;
  videoType: string;
  videoLanguage: string;
}

interface MediaReducer {
  media: MediaType | null;
  uploadedMedia: MediaType | null;
  error: string | null;
}

const initialState: MediaReducer = {
  media: null,
  uploadedMedia: null,
  error: null,
};

export default createReducer<MediaReducer>(initialState, {
  [LOAD_SUCCESS]: (state, { payload: media }) => ({
    ...state,
    media,
    error: null,
  }),
  [LOAD_FAILURE]: (state, { payload: error }) => ({
    ...state,
    media: null,
    error,
  }),
  [UPLOAD_SUCCESS]: (state, { payload: uploadedMedia }) => ({
    ...state,
    uploadedMedia,
    error: null,
  }),
  [UPLOAD_FAILURE]: (state, { payload: error }) => ({
    ...state,
    uploadedMedia: null,
    error,
  }),
});

원래는 redux-actions의 handleActions로 처리했는데 그렇게 하니까 TypeScript 변환이 복잡해 보이길래(?) typesafe-actions를 사용하기로 함
createReducer를 적용하고 interface도 선언해서 적용함

다행히
오류


ㅎㅎㅎ

겪었던 오류들

media 에서 오류 안 떠서 기뻤는데 user 파일에 똑같이 처리하니까 오류뜸

어이가 없어서

1. createReducer 오류

// modules/user.ts
...
export const login = createRequestThunk(LOGIN, userAPI.login);
export const logout = createRequestThunk(LOGOUT, userAPI.logout);
export const signup = createRequestThunk(SIGNUP, userAPI.signup);

interface UserReducer {
  login: boolean;
  isSend: boolean;
  isVerify: boolean;
  tokenExp: string;
  error: string | null;
}

const initialState: UserReducer = {
  login: false,
  isSend: false,
  isVerify: false,
  tokenExp: "",
  error: null,
};

export default createReducer<UserReducer>(initialState, {
  [LOGIN_SUCCESS]: (state, { payload: data }) => ({
    ...state,
    login: data.login,
    tokenExp: data.tokenExp,
    error: null,
  }),
  [LOGIN_FAILURE]: (state, { payload: error }) => ({
    ...state,
    login: false,
    error,
  }),
  [SIGNUP_SUCCESS]: (state) => ({
    ...state,
    error: null,
  }),
  [SIGNUP_FAILURE]: (state, { payload: error }) => ({
    ...state,
    login: null,
    error,
  }),
  [LOGOUT_SUCCESS]: (state, { payload: login }) => ({
    ...state,
    login,
    error: null,
  }),
  [LOGOUT_FAILURE]: (state, { payload: error }) => ({
    ...state,
    error,
  }),
  ...
});

근데 내가 잘못한거였다.
boolean type 선언해놓고 null 집어넣고 있었다.
많이 잘못했음.

createReducer에서 null로 넣어준 부분 false로 변경

2. useSelector 오류

Header를 수정하려고 하는데 여기서 Redux 값을 가져와서 사용하는 부분이 있었다.

const login = useSelector(({ user }) => ({
  login: user.login
}))

해당 구문에 오류가 발생했다.

// modules/index.ts
export type RootState = ReturnType<typeof persistedReducer>;

// components/Header.tsx
const login = useSelector((state: RootState) => state.user.login);

modules의 index 파일에 RootState 선언해주고 Header 코드 고쳐주니까 해결!!!

3. params 개수 오류

// components/Header.tsx
dispatch(logout());

// lib/createRequestThunk.ts
export default function createRequestThunk(type: string, request: any) {
  const SUCCESS = `${type}_SUCCESS`;
  const FAILURE = `${type}_FAILURE`;

  return (params?: any) => async (dispatch: any) => {
    dispatch({ type });
    try {
      const response = await request(params);
      dispatch({
        type: SUCCESS,
        payload: response.data.data,
      });
    } catch (e) {
      dispatch({
        type: FAILURE,
        payload: e,
        error: true,
      });
      throw e;
    }
  };
}

그리고 좀 사소한 오류인데 로그아웃 코드에서 자꾸 오류가 났다.
내 잘못 아닌줄 알고 vscode 껐다켰다 했다.

근데 내 잘못이었다.
params를 그냥 any로 해놨음
그래서 인자 안 받는 logout에서는 오류가 나더라.
물음표 추가함
해결쓰

4. 인덱스 식이 'number' 형식이 아니므로 요소에 암시적으로 'any' 형식이 있습니다.

import Cookies from "universal-cookie";
import axios, { HeadersDefaults } from "axios";

const cookies = new Cookies();

const client = axios.create({
  baseURL: URL,
  timeout: 10000,
  headers: { "Content-Type": "application/json" },
});

client.interceptors.request.use((config) => {
  config.headers.common["Authorization"] = `Bearer ${cookies.get(
    "refresh_token",
  )}`;
  return config;
});

export default client;

axios header 부분에서 오류 발생

client.interceptors.request.use((config) => {
  const token = cookies.get("refresh_token");
  if (config.headers) {
    config.headers.Authorization = token ? `Bearer ${token}` : "";
  }

  return config;
});

config.headers.common["Authorization"]을 config.headers.Authorization으로 바꿔주니까 해결됐다.
이유는 모르겠다.

5. dispatch.then()

const _handleFunc = () => {
  dispatch(func()).then();
}
// 오류 발생

const _handleFunc = async () => {
  await dispatch(func());
  // code...
}

아래 코드로 바꾸니까 로그인은 원하는대로 로직 반영됨
근데 회원가입 시 메일전송, 체크 로직에서 바로바로 state 확인을 못하고 이전 state를 확인한다.
ㅎ...

6. 인자값 개수 일치

// modules/user.ts
import { createAction } from 'typesafe-actions';

export const renewalExpires = createAction(RENEWAL_EXPIRES)();

// App.tsx
dispatch(renewalExpires(data));

인자값이 0개가 들어와야 하는데 하나만 들어온다고 오류가 났다.
분명 redux-actions 사용했을때는 괜찮았는데 이상해서 다시 redux-actions로 바꿔봤다.

된다.

createReducer 적용하면서 같이 바꿨던건데 괜히 바꿨다.

7. (오늘의) 마지막! index.js not found

index.js를 index.tsx로 바꿔주니까 코드에서 오류는 발생하지 않았지만 실행하니까 오류가 나오더라.

근데

다시 실행하니까
됨.

ㅎ...

일단 오늘은 끝

0개의 댓글