HOC(High Order Component)

studying  · 4 mins read

HOC란?

컴포넌트를 인자로 받아 새로운 컴포넌트를 반환하는 함수, HOC function

컴포넌트 로직을 재사용하기 위한 react의 고급 기술 → 로직을 한 곳에서 정의하고 많은 컴포넌트에서 로직을 공유할 수 있게 하는 추상화를 가능하게 한다.

인자로 받은 컴포넌트에 특정 기능을 부여한다.

  • 고차 컴포넌트는 사이드 이펙트가 전혀 없는 순수 함수
  • 코드의 반복을 줄일 수 있다.
  • 비지니스 로직, 뷰를 분리하기 위한 목적으로도 쓰인다.
  • 원본 컴포넌트를 변경하지 않고 조합할 수 있다.
  • 컴포넌트 로직을 재사용할 수 있다/

    ex1) 로그인 상태에 따른 토글 로직을 HOC를 사용하여 토글 기능에 따라 보여줄 컴포넌트를 인자로 전달 → withToggle HOC를 가지고 여러 곳에서 토글 기능 사용 가능!

    ex2) 모든 포스트를 나열하는 컴포넌트, 모든 댓글을 나열하는 컴포넌트 → 로직이 동일: http get 요청을 통해 데이터를 받아온 후 state에 저장, 데이터를 렌더링 → 포스트를 보여주는 컴포넌트, 댓글을 보여주는 컴포넌트를 withRequest HOC에 각각 인자로 넘겨주어 만들어진 컴포넌트 사용 → 로직을 공유!

    ex3) withRouter HOC: 라우트 컴포넌트가 아닌 곳에서 match/location/history를 사용해야 할 때 사용된다. react-router-dom 라이브러리로부터 가져와서 쓸 수 있다.

  • HOC함수의 네이밍은 주로 with로 시작

HOC 구조

const WrappedComponent = () => { return ... }
// 모듈을 export할 때 단순히 WrappedComponent가 아닌, 
// withHOC 함수에서 리턴된 enhanced WrappedComponent를 리턴하는 것. 
export default withHOC(WrappedComponent);

예시

예시 1) withToggle HOC

// refactoring 생략

const WrappedComponent1 = () => { return ... };
const WrappedComponent2 = () => { return ... };

const withToogle = (WrappedComponent) => {

  return (props) => {
    return props.show ? <WrappedComponent {...props} /> : false; 
  };
}
 
export withToggle(WrappedComponent1);
export withToggle(WrappedComponent2);

예시 2) withRequest HOC

const WrappedComponent1 = () => { return ... }; // Post component
const WrappedComponent2 = () => { return ... }; // Comment component

const withRequest = (url) => (WrappedComponent) => {
  return (props) => {
		const [data, setData] = useState(null);
    

		useEffect(()=> {
			
		 try {
        const response = await axios.get(url);
        setData(response.data);
      } catch (e) {
        console.log(e);
      }

		}, []);

      return (
        <WrappedComponent {...props} data={data}/>
      );
    };
  };

export withRequest(/* url for posts */)(WrappedComponent1);
export withRequest/* url for comments */)(WrappedComponent2);

예시 3) withRouter


import { withRouter } from 'react-router-dom';
const WithRouterSample = ({ location, match, history }) => {
  return (
    <div>
     <button onClick={() => history.goBack()}>뒤로가기</button>
      <button onClick={() => history.push('/')}>홈으로</button>
    </div>
  );
};

export default withRouter(WithRouterSample);
import WithRouterSample from 'hoc/WithRouterSample';

const UseWithRouterSample = () => {
    // ...
		return <WithRouterSample />;
};

React에서 제공하는 useParams, useHistory, useRouteMatch, useLocation 라우터 훅을 사용해서도 라우트 컴포넌트가 아닌 곳에서 match/location/history를 사용할 수 있다.

references