[한끼밀-리팩토링] 설문조사 페이지 - map으로 중복 코드 줄이기

소이뎁·2023년 5월 24일
0

한끼밀 프로젝트

목록 보기
3/5
post-thumbnail

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

🌈 Intro

동일한 컴포넌트를 연속으로 반복해서 나타내고 싶을 때, 같은 코드를 여러 번 작성하는 대신, map()으로 간결하게 작성할 수 있다.

리팩토링 전, 설문조사 페이지를 보면

<Option> 내부에서 <SurveyBox>가 4번 반복되는 것을 볼 수 있다.

function SurveyPage2({ name }) {
// ...생략...
  return (
    <article>
      <SurveyH3>{name ? `${name}` : `당신의`} 활동량을 알려주세요</SurveyH3>
      <ExplanationDiv>
        정확한 일일 권장 섭취량을 계산하는데 사용됩니다.
      </ExplanationDiv>
      <Option>
        <SurveyBox
          id="NOT_ACTIVE"
          title="비활동적"
          group="active"
          detail="대부분 앉아있는 직장인 등"
          changeHandler={dispatchActive}
          checked={active === 'NOT_ACTIVE'}
        />
        <SurveyBox
          id="LOW_ACTIVE"
          title="저활동적"
          group="active"
          detail="주 1~3회 가벼운 운동"
          changeHandler={dispatchActive}
          checked={active === 'LOW_ACTIVE'}
        />
        <SurveyBox
          id="NORMAL_ACTIVE"
          title="활동적"
          group="active"
          detail="매일 30분 이상 자발적 운동"
          changeHandler={dispatchActive}
          checked={active === 'NORMAL_ACTIVE'}
        />
        <SurveyBox
          id="HIGH_ACTIVE"
          title="매우 활동적"
          group="active"
          detail="주로 선수, 거의 매일 2회 운동"
          changeHandler={dispatchActive}
          checked={active === 'HIGH_ACTIVE'}
        />
      </Option>
      <PreAndNextButtons nextHandler={nextHandler} />
    </article>
  );
}

map을 사용하기 위해

우선, <SurveyBox>의 id에 따라 props로 전달해야 하는 데이터가 다르므로 각 id를 key로 하는 explanation 객체를 생성한다.

  let explanation = {
    NOT_ACTIVE: { active: '비활동적', detail: '대부분 앉아있는 직장인 등' },
    LOW_ACTIVE: { active: '저활동적', detail: '주 1~3회 가벼운 운동' },
    NORMAL_ACTIVE: {
      active: '활동적',
      detail: '매일 30분 이상 자발적 운동',
    },
    HIGH_ACTIVE: {
      active: '매우 활동적',
      detail: '주로 선수, 거의 매일 2회 운동',
    },
  };

다음으로, map()으로 explanation의 key를 순회하면서 새로운 노드 배열(optionItem)을 생성한다. 각 props에 전해줘야 할 데이터는 explanation에서 가져온다.

  let optionItem = Object.keys(explanation).map((act) => {
    return (
      <SurveyBox
        key={act}
        id={act}
        title={explanation[act].active}
        group="active"
        changeHandler={dispatchActive}
        checked={active === act}
      >
        <div>{explanation[act].detail}</div>
      </SurveyBox>
    );
  });

중요한 것은 React가 각각의 <SurveyBox>를 식별할 수 있게 key를 부여하는 것이다. 또한, key는 prop으로 넘길 수 없기 때문에 id={act}는 그대로 둔다.

You need to give each array item a key — a string or a number that uniquely identifies it among other items in that array.
각 배열 항목에는 해당 배열의 항목들 사이에서 고유하게 식별할 수 있는 문자열 또는 숫자인 key를 부여해야 합니다.
-React 공식 문서(https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key)

Note that your components won’t receive key as a prop. It’s only used as a hint by React itself. If your component needs an ID, you have to pass it as a separate prop: <Profile key={id} userId={id} />.
컴포넌트는 key를 prop으로 받지 않는다는 점에 유의하세요. React 자체에서 힌트로만 사용됩니다. 컴포넌트에 ID가 필요한 경우 별도의 prop으로 전달해야 합니다: <Profile key={id} userId={id} />.
-React 공식 문서(https://react.dev/learn/rendering-lists#why-does-react-need-keys)

이제, 이렇게 줄일 수 있다.

4개의 <SurveyBox>optionItem이라는 하나의 변수로 나타낼 수 있다.

function SurveyPage2({ name }) {
// ...생략...
  return (
    <article>
      <SurveyH3>{name ? `${name}` : `당신의`} 활동량을 알려주세요</SurveyH3>
      <ExplanationDiv>
        정확한 일일 권장 섭취량을 계산하는데 사용됩니다.
      </ExplanationDiv>
      <Option>{optionItem}</Option>
      <PreAndNextButtons nextHandler={nextHandler} />
    </article>
  );
}

0개의 댓글