프론트엔드 첫걸음

[칼럼] React 컴포넌트를 커스텀 훅으로 제공하기 본문

개발 공부/React

[칼럼] React 컴포넌트를 커스텀 훅으로 제공하기

차정 2023. 2. 22. 16:26

https://engineering.linecorp.com/ko/blog/line-securities-frontend-3/

[커스텀 훅 도입 이전]


 원래 App 컴포넌트는 5개의 구성 요소를 가지고 있습니다. 상태 변수인 checkList와 이벤트 핸들인 handleCheckClick, isAllChecked를 계산하는 부분, 체크박스를 그리는 부분, 그리고 그 밖의 것을 그리는 부분입니다.
 이 중에서 Checks 컴포넌트를 분리하는 과정에서 App에서 빠진 것은 체크박스를 그리는 기능뿐입니다. 나머지 4개의 기능은 여전히 App에 남아 있고, 재사용할 수 없습니다.
특히 checkList가 여전히 Checks가 아닌 App에 남아있는 것은 주목할 만합니다. App이 '다음' 버튼의 disabled 속성을 계산해야 하기 때문입니다. 이 부분이 그림에서 isAllChecked인데요. 이건 checkList에서 계산합니다. 따라서 필연적으로 checkList도 App에 있어야 합니다.

App 은 원래 '모두 체크되었는지'에만 관심이 있습니다. '무엇이 체크되었는지'에 관한 정보 관리는 Checks에 맡기고 싶을 겁니다.

 

 

[커스텀 훅 도입 이후]

 App이 알고싶은 정보인 'Checks를 사용한다'는 것 자체를 커스텀 훅 안으로 이동시켰다.
App은 useChecks 반환 값으로 isAllChecked와 renderChecks를 받습니다. 이것으로 App의 역할이 아주 명확해졌습니다. '체크박스 목록을 적절한 곳에 그릴 것'과 '체크박스 이외의 부분을 그릴 것', 그리고 '체크박스가 모두 체크되어 있는지에 따라 표시를 바꿀 것'입니다. 이번에 만든 useChecks는 호출자에게 딱 해당 정보만 전달하도록 설계했습니다. 그리고 체크박스를 그릴 때 공통화할 수 있는 부분은 깔끔하게 useChecks 안으로 이동시켰습니다. 

 

커스텀훅
useChecks.js

export const useChecks = (labels) => {
  const [checkList, setCheckList] = useState(() => labels.map(() => false)) //[false, false, false] 로 초기화
 
  const handleCheckClick = (index) => {
    setCheckList((checks) => checks.map((c, i) => (i === index ? !c : c)))
  }
 
 //checkList의 모든 값이 true면 isAllChecked도 true
  const isAllChecked = checkList.every((x) => x)
 
  const renderChecks = () => (
    <Checks checkList={checkList} labels={labels} onCheck={handleCheckClick} />
  )
 
  return [isAllChecked, renderChecks]
}

useChecks라는 커스텀 훅은 체크 박스의 정의(string[])를 받아서 '이 정의를 레이블로 하는 체크 박스를 관리한다'라는 로직을 내포합니다. 반환 값으로는 '모두 체크되어 있는지'와 '체크박스를 렌더링하는 함수'를 반환합니다.

 

App.js

const App = () => {
  const [isAllChecked, renderChecks] = useChecks(labels)
 
  return (
    <div>
      {renderChecks()}
      <p>
        <button disabled={!isAllChecked}>다음</button>
      </p>
    </div>
  )
}

 

 

[결론]

커스텀훅은 컴포넌트 분할과 달리 컴포넌트 로직 자체를 분할하거나 재사용할 때 사용한다.
로직만을 재사용가능한 형태로 뽑아서 캡슐화 하여 간결한 인터페이스를 제공한다.

 

'개발 공부 > React' 카테고리의 다른 글

useLocation  (0) 2023.07.18
QueryClient 대신 useQueryClient 사용하는 이유  (0) 2023.02.20
map으로 순회하는 component마다 ref 를 달 때  (0) 2023.01.10
리액트 절대경로 사용하기  (0) 2023.01.05
구글로그인 추가  (0) 2022.10.20