[한끼밀-리팩토링] 설문조사 페이지 - input이 3개이면 함수도 3개여야 할까?(feat.Redux-Toolkit)

hameee·2023년 5월 25일
0

한끼밀 프로젝트

목록 보기
5/5
post-thumbnail

🔗 한끼밀 링크 http://www.hankkimeal.kro.kr

🌈 Intro

아래 설문조사 페이지에는 3개의 <input>이 있다. 설문조사 정보는 모아서 한꺼번에 서버로 보내야 하기 때문에 전역 상태로 관리한다.

리팩토링 전, 내 코드는

정말 단순하게 input이 3개라 reducer 함수도 3개이다.

// 가독성을 위해 설명에 필요한 부분만 가져왔습니다.
const surveyQuestionSlice = createSlice({
  name: 'surveyQuesiton',
  initialState: { age: '', height: '', weight: ''},
  reducers: {
    setAge: (state, action) => {
      state.age = action.payload;
    },
    setHeight: (state, action) => {
      state.height = action.payload;
    },
    setWeight: (state, action) => {
      state.weight = action.payload;
    },
  },
});

이게 아닌 것 같은데...

라는 생각이 강하게 든다. React 공식 문서를 보다 보니 아래와 같은 내용이 있다. Redux store가 아닌 useState에 대한 설명이지만 내 코드에도 적용할 수 있을 것 같다.

여러 필드에 단일 이벤트 핸들러 사용하기
객체 정의 내에서 []를 사용하여 동적 이름을 가진 프로퍼티를 지정할 수도 있습니다.
-React 공식 문서(https://react.dev/learn/updating-objects-in-state#using-a-single-event-handler-for-multiple-fields)

아래는 공식 문서의 예시이다. [e.target.name]으로 객체의 키를 동적으로 만들어 3개의 속성을 1개의 핸들러로 조정하고 있다.

import { useState } from 'react';

export default function Form() {
  const [person, setPerson] = useState({
    firstName: 'Barbara',
    lastName: 'Hepworth',
    email: 'bhepworth@sculpture.com'
  });

  function handleChange(e) {
    setPerson({
      ...person,
      [e.target.name]: e.target.value
    });
  }

  return (
    //...생략...
  );
}

Redux-Toolkit 코드에 적용하면

state를 복사할 필요 없이 직접 변경하는 것처럼 작성하면 된다.

To make things easier, createReducer uses immer to let you write reducers as if they were mutating the state directly.
더 쉬운 작업을 위해, createReducerimmer를 사용하여 state를 직접 변경하는 것처럼 reducer를 작성할 수 있습니다.
-Redux-Toolkit 공식 문서(https://redux-toolkit.js.org/api/createReducer#direct-state-mutation)

const surveyQuestionSlice = createSlice({
  name: 'surveyQuesiton',
  initialState: { age: '', height: '', weight: ''},
  reducers: {
    setProfile: (state, action) => {
      state[action.payload.id] = action[action.payload.value];
    },
  },
});

물론 보내줄 때도 동적 이름에 필요한 값을 같이 보내주어야 한다.

// 리팩토링 전
const dispatchAge = (e) => {
  dispatch(setAge(e.target.value));
};

// 리팩토링 후
const dispatchProfile = (e) => {
  const { id, value } = e.target;
  dispatch(setProfile({ id, value }));
};

0개의 댓글