본문 바로가기
항해99/실전 WIL | TIL

[TIL-012] 리덕스 실습 및 이해, styled-component 리팩토링

by junvely 2023. 4. 23.

Today목표 : 4/22일 리덕스 실습 및 이해, styled-component 리팩토링


알게된 점,

 

Redux 상태관리 state의 구조

state를 처음에는 다음과 같이 배열로 구상하였다.

const initialTodos = [
  {
    id: 1,
    title: "리액트 공부중",
    text: "재밌는 리액트 공부하기!",
    isDone: false,
  },
];

리턴도 역시 배열로 리턴해 주었었다.

export const todos = (state = initialTodos, action) => {
  switch (action.type) {
    case ADD_TODO:
      return [...state, action.payload];

    case DELETE_TODO:
      const deletedTodos = state.filter((todo) => todo.id !== action.payload);
      return deletedTodos;

    case TOGGLE_CHANGE:
      const changedTodos = state.map((todo) => {
        if (todo.id === action.payload) {
          return {
            ...todo,
            isDone: !todo.isDone,
          };
        }
        return todo;
      });
      break;

state를 배열로 만든 이유는 todos는 todolist에서 더 확장될 가능성은 없어 보여 useState에서 사용했던 대로 하나의 형식에 맞게  독립적인 배열 state로 두고 관리해야 한다고 생각했었다.

그런데, 컴포넌트에서 todos state를 그냥 가져오기만 했는데 다음과 같은 에러가 났다.

function Modal() {
  const params = useParams();
  const todo = useSelector((state) => state.todos);
  console.log(...todo);
  
  return <>{todo}</>;
}

❗"개체는 React 하위 개체로 사용할 수 없습니다(키가 {id, 제목, 텍스트, isDone}인 개체 발견). 하위 컬렉션을 렌더링하려면 배열을 대신 사용합니다." => 나는 todos배열 내부에 객체 형식으로 todo를 넣어 주었는데..? key가 배열이라고 인식하는건가..? 도대체 왜..? 한시간 동안 계속되는 디버깅 끝에 든 생각은..

1. 에러와 관계는 없지만, 혹시 todos 위에 객체로 감싸져 있는 것인가? 해서 혹시나 하여 store파일을 열어보았는데...

const rootReducer = combineReducers({
  todos: todos,
});
const store = createStore(rootReducer);

그게 맞았다... reducer에서 객체로 todos의 키 : todos state를 가져오고 있었다....이 사실을 처음 알았다.

사실 이것은 문제가 아니지만 배운대로 그냥 사용하면서 reducer 구조 자체를 신경 안쓰고 있었다는 것이 좀 충격이었다.

 

2. 에러가 발생한 것은 다음 jsx문에서 { } 안에서 todos 배열을 불렀기 때문이었다.

  return <> {todo} </>;

"개체는 React 하위 개체로 사용할 수 없습니다" 따라서 이 부분만 풀어서 출력해주면 해결됐다.

 

데이터 형식을 어떻게 짰을까 궁금해서 답안 소스코드를 보니 다음과 같이 객체 안에 키값을 주고 => todos와 todo를 따로 관리해 주었다.

const initialState = {
  todos: [
    {
      id: "1",
      title: "리액트",
      body: "리액트를 배워봅시다",
      isDone: false,
    },
  ],
  todo: {
    id: "0",
    title: "",
    body: "",
    isDone: false,
  },
};

❗마치 JSON 데이터 형식을 보는 듯 했다. 만약 확장성을 고려하여 todos 외의 관련 데이터들도 같이 관리한다면 이렇게 더 많은 내용들을 관리할 수 있도록 객체로 한 번 더 감싸주면 좋을 것 같다.

 

 

Styled-components 리팩토링

어제 리팩토링 했던 부분이 만족스럽지 않아 다시 리팩토링 했다...

ButtonStyles.js 1차 리팩토링

export const buttonWidth = {
  add: "200px",
};

export const buttonBgColor = {
  delete: "#ccc",
  done: "#64dc95",
  notYet: "#6736ed94",
};

export const buttonHoverBgColor = {
  delete: "#696969",
  done: "#17d164",
  notYet: "#6836ed",
};

css속성별로 해당하는 type에 맞게 객체 키값으로 접근하도록 하였다. 색상코드를 직접 관리하는게 유지보수도 어렵고 가독성에도 안좋다고 생각했다.

 

ButtonStyles.js 2차 리팩토링

// them.js 분리
export const colors = {
  gray: "#696969",
  lightGray: "#ccc",
  green: "#17d164",
  lightGreen: "#64dc95",
  navy: "#38139efc",
  lightNavy: "#6736ed94",
  purple: "#a235fc",
  lightPurple: "#bf79f8",
};

export const width = {
  small: "200px",
};

//button
export const buttonBgColor = {
  delete: colors.lightGray,
  done: colors.lightGreen,
  notYet: colors.lightNavy,
};

export const buttonHoverBgColor = {
  delete: colors.gray,
  done: colors.green,
  notYet: colors.navy,
};

color값들을 따로 파일을 분리해 변수로 설정해 유지보수가 편하고 가독성이 훨씬 좋아졌다.

 

ButtonStyles.js 3차 리팩토링

export const buttonColors = {
  delete: {
    normal: colors.lightGray,
    hover: colors.gray,
  },
  done: {
    normal: colors.lightGreen,
    hover: colors.green,
  },
  notYet: {
    normal: colors.lightNavy,
    hover: colors.navy,
  },
};

버튼 type에 맞게 한 번에 color스타일을 관리할 수 있도록 리팩토링하였다. 훨씬 더 유지보수나 가독성이 좋아졌다. 여기서 추가적으로 border등이 추가되어도 키값만 추가하면 된다. 또 저 type들이 아닌 경우는 button에 직접 colors에 접근해 색상을 전달하면 바로 적용가능하도록 리팩토링 하였다.