본문 바로가기

카테고리 없음

잘 쪼갤 수 있을까(2)

저번 주부터 인턴 생활이 시작돼서, 심지어 회사가 판교라 집에서 왕복 2시간 반이 조금 넘게 걸린다. 뭐 이래저래 다 핑계지만..

 

암튼 SettingPage를 차근차근 쪼개야 하는데, deviceId를 불러오거나 audioStream을 바꾸는 것들이 모두 비동기 작업이고, 완전 똑같이는 아니지만 셋팅된 device관련 정보를 mainPage에서도 사용할 것이기 때문에 redux 미들웨어를 써야 한다.

 

지금까지는 벨로퍼트님의 튜토리얼만 보고 리덕스 보일러 플레이트를 따라 만들고, 적용하고 하는 수준이었는데 이런 귀찮은 작업들을 모두 해결해주는 redux toolkit이라는 도구가 있어서 일단 profile.ts에 적용했다. 

 

적용 전엔 이랬는데,

import {PayloadAction} from '@reduxjs/toolkit';

import {
  AvatarImageEnum,
  AvatarImageEnumMax,
  AvatarImageEnumMin,
  avatarImageMDs,
} from '../pixi/metaData/ImageMetaData';

// action type
const CHANGE_AVATAR = 'profile/CHANGE_AVATAR' as const;
const CHANGE_NICKNAME = 'profile/CHANGE_NICKNAME' as const;

// action 생성 함수
export function changeAvatar(direction: number) {
  return <const>{
    type: CHANGE_AVATAR,
    direction,
  };
}

export function changeNickname(nickname: string) {
  return <const>{
    type: CHANGE_NICKNAME,
    nickname,
  };
}

type Action =
  | ReturnType<typeof changeNickname>
  | ReturnType<typeof changeAvatar>;

type ProfileState = {
  avatar: number;
  nickname: string;
};

const profileState = {
  avatar: 0,
  nickname: `익명의 ${avatarImageMDs[0].avatarKoreanName}`,
};

function profile(state = profileState, action: Action): ProfileState {
  switch (action.type) {
    case CHANGE_AVATAR: {
      // 로직
      let newAvatar = state.avatar + action.direction;
      if (newAvatar < AvatarImageEnumMin) newAvatar = AvatarImageEnumMax;
      else if (newAvatar > AvatarImageEnumMax) newAvatar = AvatarImageEnumMin;
      return {...state, avatar: newAvatar};
    }
    case CHANGE_NICKNAME: {
      if (action.nickname === '') {
        const nickname = `익명의 ${
          avatarImageMDs[state.avatar].avatarKoreanName
        }`;
        return {...state, nickname};
      } else {
        return {...state, nickname: action.nickname};
      }
    }
    default:
      return state;
  }
}

export default profile;

 

적용 후엔 이렇게 됐다!

import {createSlice, PayloadAction} from '@reduxjs/toolkit';
import {
  AvatarImageEnumMax,
  AvatarImageEnumMin,
  avatarImageMDs,
} from 'pixi/metaData/ImageMetaData';

type ProfileState = {
  avatar: number;
  nickname: string;
};

const initialState: ProfileState = {
  avatar: 0,
  nickname: `익명의 ${avatarImageMDs[0].avatarKoreanName}`,
};

export const profileSlice = createSlice({
  name: 'profile',
  initialState,
  reducers: {
    changeAvatar: (state, action: PayloadAction<number>) => {
      if (state.avatar + action.payload > AvatarImageEnumMax) {
        state.avatar = AvatarImageEnumMin;
      } else if (state.avatar + action.payload < AvatarImageEnumMin) {
        state.avatar = AvatarImageEnumMax;
      } else {
        state.avatar += action.payload;
      }
    },
    changeNickname: (state, action: PayloadAction<string>) => {
      if (action.payload === '') {
        state.nickname = `익명의 ${
          avatarImageMDs[state.avatar].avatarKoreanName
        }`;
      } else {
        state.nickname = action.payload;
      }
    },
  },
});

export const {changeAvatar, changeNickname} = profileSlice.actions;

export default profileSlice.reducer;

 

액션의 타입, 액션 생성함수를 따로 만들지 않아도 되고 useSelector, useDispatch 대신 둘을 감싸서 useAppSelector, useAppDispatch라는 커스텀 훅을 만들었고 귀찮게 자꾸 state의 타입을 명시하지 않아도 된다(이게 생산성 증대에 얼마나 기여할지는 모르겠지만..)

 

암튼 이번 주 안에는 꼭 SettingPage를.. 예쁘게 쪼개길.. 알겠니? 미래의 나야