React HOC란, Higher-order component를 나타내는 것으로,
감싸진 구성요소(컴포넌트)의 렌더링 출력을 제어해 모든 종류의 작업을 수행할 수 있게 되는
컴포넌트 재사용 패턴이다.
HOC는 하나의 함수인데, 리액트 컴포넌트 작성 시 반복될 수 있는 코드들을 HOC를 만들어 해결해 줄 수 있다.
주로 HOC를 만들때는 'with~'의 형식으로 짓는다.
HOC는 간략히 설명하자면 parameter로 감싸질 하위 컴포넌트를 받아오고, 함수 내부에서 새 컴포넌트를 만든 다음에 해당 컴포넌트 안에서 파라미터로 받아온 컴포넌트를 렌더링한다.
HOC 컴포넌트의 render() 메소드 안에서 인자로 받은 컴포넌트를 리턴하는데,
이는 HOC가 받게되는 props를 전달해 props를 조작하거나/ refs를 통해 인스턴스에 바로 접근하거나 / 상태를 추상화하거나 / WrappedComponent를 다른 요소로 래핑하는 것이 가능해지게 만들어준다.
예를 들면, WrappedComponent로 전달되는 props를 읽고, 추가하고, 편집하고, 제거할 수 있다. 단, 주의점이 있다면 HOC가 WrappedComponent의 props를 손상시키지 않도록 name space를 이용하는 것이 좋다. 즉,새 props를 추가하는 것도 가능하다.
const ppHOC = (WrappedComponent) => {
return class PP extends React.Component {
render() {
const newProps = {
user: currentLoggedInUser
}
return <WrappedComponent {...this.props} {...newProps} />
}
}
}
const refsHOC = (WrappedComponent) => {
return class RefsHOC extends React.Component {
proc(wrappedComponentInstance) {
wrappedComponentInstance.method()
}
render() {
const props = Object.assign({}, this.props, {ref: this.proc.bind(this)})
}
}
}
WrappedComponent에 props 및 콜백을 제공해 똑똑한 컴포넌트가 멍청한 컴포넌트를 처리하는 (Container-presenter 패턴) 방식과 유사하게 상태를 추상화 시킬 수 있다.
즉, 상태를 추상화시켜놓고, 상위 컴포넌트를 변경했을 때 하위 컴포넌트가 그 props를 그대로 받아와 동기화되는 방식으로 만들어줄 수 있다.
WrappedComponent를 다른 컴포넌트/엘리먼트로 래핑해,
단순히 부모 컴포넌트에서 수행할 수 있는 작업보다 더 많은 유연성을 제공한다.
예시
const ppHOC = (WrappedComponent) => {
return class PP extends React.Component {
render() {
return (
<div style={{display: 'block'}}>
<WrappedComponent {...this.props}/>
</div>
)
}
}
}
상속을 HOC를 이용해 간단히 구현하고, WrappedComponent 인스턴스에 접근하게 할 수 있다. 즉, state, props, 컴포넌트 및 lifecycle hook 및 렌더링 메소드에 접근할 수 있다.
const IamHOC = (WrappedComponent) => {
return class Enhancer extends WrappedComponent {
render() {
return super.render()
}
}
}
리턴된 HOC클래스인 Enhancer는 WrappedComponent를 확장하며 관계성이 역전이 되어,
HOC가 WrappedComponent 인스턴스에 접근할 수 있게 된다.
HOC는 래핑된 구성요소의 렌더링 출력을 제어하고 이를 사용해 모든 종류의 작업을 수행하다 - 즉, Render Proxy와 같이 render에서 출력한 모든 React element에서 props를 읽고, 추가하고, 편집하고, 제거할 수 있다. 즉, 요약해 정리하자면 render메소드에서 출력한 모든 React element 트리를 읽고 수정할 수 있다. 그래서 조건부로 엘리먼트 트리를 표시하거나, 스타일링을 목적으로 엘리먼트의 트리를 래핑할 수 도 있다. 한 예시로 React-redux또한 Pros proxy방식으로 구현되어있다.
다음 시리즈에서는 HOC를 실제로 어떻게 만드는지에 대한 활용법을 이야기하고자한다.