React - Should have a queue.

2021. 7. 3. 15:27프로그래밍/React.js

728x90

어제 룰루랄라 개발을 하다가 의문의 버그로 약 2시간이 날아갔다.
버그 내용부터 살펴보자.

// SurveyPage.tsx
const SurveyPage = () => {
  ...

  return (
    <div>
      {questionNum >= 0 && [
        WeightSurvey,
        ScreenSizeSurvey,
        BrandSurvey,
        BudgetSurvey,
        HelpSurvey,
      ][questionNum]({ survey: question, onNext: handleNext })}
      <Button onClick={() => handleNext("", "")}>치트키</Button>
    </div>
  );
}

// BrandSurvey.tsx
const BrandSurvey = () => {
  const [formats, setFormats] = useState(['bold', 'italic']);
  
  return (
  	<div />
  );
}

이 BrandSurvey에 useState를 넣자, 다음과 같은 에러가 발생하였다.

이게 뭔지 검색을 열심히 해봤지만 명확한 해답이 나오지는 않았다.

그래서 React Hook 설명서를 다시 살펴보았다.
https://ko.reactjs.org/docs/hooks-rules.html

 

Hook의 규칙 – React

A JavaScript library for building user interfaces

ko.reactjs.org

여기에 이런 말이 있다.

최상위(at the Top Level)에서만 Hook을 호출해야 합니다

반복문, 조건문 혹은 중첩된 함수 내에서 Hook을 호출하지 마세요. 

한번 쭉 읽었을 때도 뭔 소린지 모르겠어서 멍을 때리다가,

오늘 아침에 런닝머신을 뛰다가 생각이 정리가 되었다.

BrandSurvey가 호출되냐에 따라서 hook의 순서가 바뀔수 있구나!

이게 무슨 말인지를 보려면 이 부분을 살펴봐야 한다.

위의 예시에서는 if에 따라서 useEffect(persistForm)의 호출 여부가 갈리기 때문에,
1->2->3->4의 순서가 깨지게 되면서 문제가 생긴다.

나의 예시도 같다.

만약 questionNum이 2가 아닌 경우에는 useState가 호출되지 않으면서, Hook의 순서가 변하게 된다.
정확히는 Hook 호출의 신뢰가 깨진다.


해결 방법

내가 생각한 해결 방법은 두가지다.

첫번째는 군대식 방법이다. 하위 컴포넌트(BrandSurvey)에서 사용되는 useState를
상위 컴포넌트인 SurveyPage에서 선언하는 것이다.
너무 역겨운 방식이니 예시는 적지 않겠다.

두번째는 모든 컴포넌트를 호출하는 것이다.
즉, 지금은 특정 컴포넌트중에 하나만 render했다면, 모든 컴포넌트를 render한 다음에 visible 여부를 부여하는 것이다.
이 visible은 임의의 변수명이고, 내부적으로 이 visible여부에 따라 안 보이게 해야한다.

const pages = [WeightSurvey, ScreenSizeSurvey, BrandSurvey, BudgetSurvey, HelpSurvey];

return (
  <div>
    {_.map(pages, (Comp, i) => Comp({ survey: question, onNext: handleNext, visible: i === questionNum }))}
    <Button onClick={() => handleNext("", "")}>치트키</Button>
  </div>
);

느낀 점

내가 지금껏 겉핥기의 공부를 하고 있었다는 것을 느낀다.

사실 hook을 그냥 함수형식의 React Component 정도로 해석하고 있었다.

하지만 hook 설명을 정독하며 느낀 점은 useState와 같은 것이 훅이며, 
함수 형식의 Component는 그냥 Class형식을 더이상 사용하지 않아도 되는 것이었다.

최근에 문과중에서도 코딩을 배워서 취직을 하려는 사람이 늘어난다는 얘기를 자주 듣는다.

근데 과연 그 사람들보다 내가 더 나은게 있을까? 라는 생각이 든다.

물론 더 낫긴하지. 하지만 이런 식의 겉핥기, 기능 위주의 공부와 학습을 하는 나 자신은
발전이 어렵다는 생각이 들었다.

그런 이유로 오늘부터 훅을 집중 탐구한다.