일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- React 18
- Nextjs
- react
- getUTCDate
- react-helmet
- Nextjs React 18
- Babel
- next13 head
- notFound()
- codingtest
- Programmers
- context
- RTK Query
- background setttimeout
- react hook
- CSS
- 고급안내서
- background setInterval
- Next13
- React 공식문서
- background tab
- React 고급 안내서
- Render Props
- React API 참고서
- React 고급안내서
- hook
- React 18 Nextjs
- background: url
- Javascript
- React18
- Today
- Total
akjfal
고차 컴포넌트 본문
HOC는 컴포넌트 로직을 재사용하기 위한 React의 기술로, 구성적 특징에서 나오는 패턴이며, 컴포넌트를 가져와 새 컴포넌트를 반환하는 함수입니다.
컴포넌트는 props를 UI로 변환하는 반면, HOC는 컴포넌트를 새로운 컴포넌트로 변환합니다.
고차 컴포넌트는 Redux의 connect와 Relay의 createFragmentConmtainer와 같은 서드파티라이브러리에서 자주 볼 수 있습니다.
Cross-Cutting Concerns에 HOC 사용하기
컴포넌트는 React의 코드 재사용의 기본 단위인데, 어떤 패턴은 기존 컴포넌트에 잘 적용되지 않을 수 있습니다.
해당 코드는 외부데이터를 구독해 댓글목록을 렌더링하는 CommentList라는 컴포넌트입니다.
import React, { useEffect, useState } from 'react';
function CommentList({}) {
// DataSoruce는 글로벌 데이터 소스입니다.
const [comments, setComments] = useState(DataSource.getComments());
useEffect(() => {
// 리스터 추가
DataSource.addChangeListener(handleChange);
// 리스너 제거
return DataSrouce.removeChangeListenr(handleChange);
}, []);
const handleChange = () => {
// 데이터 소스 변경될때 마다 comments를 업데이터
setComments(DataSource.getComments());
};
return (
<div>
{comments.map((comment) => {
return <Comment comment={comment} key={comment.id} />;
})}
</div>
);
}
그리고 블로그 포스트를 구독하기 위해 위와 비슷한 컴포넌트를 작성합니다.
function BlogPost({ id }) {
const [blogpost, setBlogPost] = useState(DataSource.getBlogPost(id));
useEffect(() => {
DataSource.addChangeListener(handleChange);
return DataSrouce.removeChangeListenr(handleChange);
}, []);
const handleChange = () => {
setBlogPost(DataSource.getBlogPost(id));
};
return <TextBlock text={blogpost} />;
}
대부분의 구현체는 동일하지만, 다른 메서드 호출과 다른 렌더링 결과가 차이점인 두 컴포넌트이기 때문에, 하나의 로직을 공유하도록 추상화 하는 작업이 필요합니다. 이러한 경우에 고차 컴포넌트를 사용하는 것이 좋습니다.
이를 위해 구독한 데이터를 prop으로 전달받는 자식 컴포넌트를 파라미터 중 하나로 받는 함수를 만듭니다.
const CommentListWithSubscripotion = withSubscription(
CommentList,
(DataSource) => DataSource.getComments()
);
const BlogPostWithSubscription = withSubscription(
BlogPost,
(DataSource, props) => DataSource.getBlogPost(props.id);
);
첫번째 파라미터는 래핑된 컴포넌트고, 두번째는 DataSource와 현재 props를 가지고 컴포넌트에서 관심 있는 데이터를 검색합니다.
function withSubscription(WrappedComponent, selectData){
return function(props) {
const [state, setState] = useState(selectData(DataSource, props);
useEffect(() => {
DataSource.addChangeListener(handleChange);
return DataSrouce.removeChangeListenr(handleChange);
}, []);
const handleChange = () => {
setBlogPost(DataSource.getBlogPost(id));
};
return (
<WrappedComponent data={state} {...props} />
)
}
고차 컴포넌트는 기존 컴포넌트를 수정하지도 않고, 상속을 사용하지도 않으며, 원본 컴포넌트를 컨테이너 컴포넌트로 감싸서 조합합니다. 따라서 사이드 이펙트가 전혀 없는 순수 함수입니다.
고차 컴포넌트와 컨테이터 컴포넌트는 유사하다고 느낄수 있는데, 컨테이터 컴포넌트는 high-level과 low-level 관심사를 분리하는 전략이고, state관리, UI렌더링 처리를 처리하는 컴포넌트의 props로전달합니다. HOC는 컨테이너를 그 구현체 중 일부로 사용하고 있습니다.
래핑된 컴포넌트를 통해 관련없는 Props 전달하기
HOC는 컴포넌트에 기능을 추가하는데, 컴포넌트의 정의를 변경하서는 안되며, 고차컴포넌트를 통해 반환된 컴포넌트는 기존과 비슷한 인터페이스가 있어야 합니다. 또한 특정 항목에 관련없는 props만을 활용해야 합니다.
단 class에서 hook으로 넘어오면서 HOC를 사용하기보다 hook을 사용해서 하는 편이 더욱 편해지는 경우가 많아졌으므로, 어떤 것을 사용할지 고려해봐야 합니다.
'(구)React 공식문서 > 고급 안내서' 카테고리의 다른 글
JSX 이해하기 (0) | 2023.02.17 |
---|---|
다른 라이브러리와 통합하기 (0) | 2023.02.16 |
Fragment (0) | 2023.02.16 |
Ref 전달하기 (0) | 2023.02.16 |
Error Boundaries (0) | 2023.02.16 |