고차 컴포넌트는 컴포넌트를 가져와 새 컴포넌트를 반환하는 함수입니다.
고차 컴포넌트(HOC, Higher Order Component)는 컴포넌트 로직을 재사용하기 위한 React의 고급 기술입니다. 고차 컴포넌트(HOC)는 React API의 일부가 아니며, 리액트의 구성적 특성에서 나오는 패턴입니다.
공식문서에서는 횡단 관심사(Cross-Cutting Concerns) 문제를 해결하는 데 쓰인다고 언급합니다.
횡단 관심사(Cross-Cutting Concerns)란?
비즈니스 로직과 구분되는 공통 기능(ex. 로깅, 로딩, 보안, 트랜잭션 등)
공식 문서에서는 대부분의 경우 Hooks로 대체 가능하다고 말합니다.
클래스 컴포넌트로만 개발해야 했을 때, 주로 고차 컴포넌트는 생명주기에 종속적이지 않으면서 중복된 코드를 분리하기 위해서 사용했습니다. 그러다보니 HOC가 반환하는 중복되는 컴포넌트 레이어들이 쌓이는 문제가 발생했습니다.
하지만 Hooks가 릴리즈되면서 생명주기가 단순화 되었고, 공통의 코드 분리가 필요한 경우에는 custom hook을 사용하면 해결 할 수 있게 되었습니다. custom hooks를 사용하면 컴포넌트가 중첩 되지 않아서 hoc에서 발생했던 문제를 해결 할 수 있습니다.
더 구체적으로 정리해보자면,
아래는 logger API에 모든 페이지 뷰를 기록하는 예제입니다.
import React, { useEffect } from 'react';
const withLogging = Component => props => {
useEffect(() => {
fetch(`/logger?location=${ window.location}`);
}, []);
return <Component {...props } />;
};
export default withLogging;
고차 컴포넌트를 조합하여 아래와 같이 사용할 수 있습니다.
import compose from 'ramda';
import withRedux from './with-redux.js';
import withAuth from './with-auth.js';
import withLogging from './with-logging.js';
import withLayout from './with-layout.js';
const page = compose(
withRedux,
withAuth,
withLogging,
withLayout('default'),
);
export default page;
위와 같이 사용했을 경우 컴포넌트 계층 구조는 아래와 같습니다.
<withRedux>
<withAuth>
<withLogging>
<withLayout>
<MyPageComponent />
</withLayout>
</withLogging>
</withAuth>
</withRedux>
실제로 아래와 같이 적용할 수 있습니다.
import page from '../hocs/page.js';
import MyPageComponent from './my-page-component.js';
export default page(MyPageComponent);