FrontEnd/React
동일한 패턴이 여러 컴포넌트에서 쓰이고 있다면? - React 고차 컴포넌트로 해결하기!
CoderHan
2023. 1. 1. 23:05
반응형
고차 컴포넌트란?
"고차 컴포넌트는 컴포넌트를 가져와 새 컴포넌트를 반환하는 함수이다."라고 공식 홈페이지에서 정의하고 있다.
규모가 큰 애플리케이션에서 DataSouce에 접근하여 SetState를 호출하는 동일한 패턴이 반복적으로 발생할 때 유용하다.
class CommentList extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
// "DataSource" 는 글로벌 데이터 소스입니다.
comments: DataSource.getComments()
};
}
componentDidMount() {
// 변화감지를 위해 리스너를 추가합니다.
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
// 리스너를 제거합니다.
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
// 데이터 소스가 변경될때 마다 comments를 업데이트합니다.
this.setState({
comments: DataSource.getComments()
});
}
render() {
return (
<div>
{this.state.comments.map((comment) => (
<Comment comment={comment} key={comment.id} />
))}
</div>
);
}
}
//--------------------------------
class BlogPost extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
blogPost: DataSource.getBlogPost(props.id)
};
}
componentDidMount() {
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
this.setState({
blogPost: DataSource.getBlogPost(this.props.id)
});
}
render() {
return <TextBlock text={this.state.blogPost} />;
}
}
위 두 컴포넌트는 DataSouce에 접근하여 DataSource.getBlogPost, DataSource.getComments를 이용해
State를 설정한다.하는 일은 다르지만 비슷한 패턴으로 작성되었으므로 이를 위한 추상화가 필요하다.
const CommentListWithSubscription = withSubscription(
CommentList,
(DataSource) => DataSource.getComments()
);
const BlogPostWithSubscription = withSubscription(
BlogPost,
(DataSource, props) => DataSource.getBlogPost(props.id)
);
이런식으로 withSubscription이라는 일반함수를 통해 두 컴포넌트를 구성했다.
/ 이 함수는 컴포넌트를 매개변수로 받고..
function withSubscription(WrappedComponent, selectData) {
// ...다른 컴포넌트를 반환하는데...
return class extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
data: selectData(DataSource, props)
};
}
componentDidMount() {
// ... 구독을 담당하고...
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
this.setState({
data: selectData(DataSource, this.props)
});
}
render() {
// ... 래핑된 컴포넌트를 새로운 데이터로 랜더링 합니다!
// 컴포넌트에 추가로 props를 내려주는 것에 주목하세요.
return <WrappedComponent data={this.state.data} {...this.props} />;
}
};
}
withSubscription함수는 래핕된 컴포넌트를 새로운 데이터로 렌더링하는 것이 특징이다!
래핑된 컴포넌트는 새로운 props, data와 함께 컨테이너의 모든 props를 전달받고, 이 데이터는 출력에 사용됩니다.
이런식으로 코드의 재사용성을 높일 수 있습니다.
자세한 내용은 공식홈페이지를 참고하세요!
https://ko.reactjs.org/docs/higher-order-components.html
고차 컴포넌트 – React
A JavaScript library for building user interfaces
ko.reactjs.org
반응형