여러개의 컴포넌트들을 조합하는것
조합방법에 따라 Composition 사용기법이 나뉜다.
하위 컴포넌트를 포함하는 형태의 합성방법
범용적인 ‘박스’ 역할을 하는 Sidebar 혹은 Dialog와 같은 컴포넌트는, 자신의 하위 컴포넌트를 미리 알 수 없다.
이러한 컴포넌트에서는 children
이라는 prop을 사용해서 조합한다.
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
FancyBorder컴포넌트 안에 있는 모든 jsx태그는 children으로 전달되어 결과적으로 파란색 테두리로 모두 감싸지는 결과가 나온다.
여러개의 chidren집합이 필요한 경우는 어떻게 할까 ?
직접 별도로 props를 정의해서 각각 원하는 컴포넌트를 넣어주면된다.
/*
SplitPane-left, SplitPane-right는 props로 받아서
각각 왼쪽 오른쪽에 다른것을 나타낸다.
*/
function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left}
</div>
<div className="SplitPane-right">
{props.right}
</div>
</div>
);
}
function App() {
return (
<SplitPane
left={
<Contacts />
}
right={
<Chat />
} />
);
}
WelcomeDialog는 Dialog의 특수한 경우라고 할 수 있다.
Dialog는 모든종류의 Dialog를 포함하므로 범용적인 의미고,
WelcomeDialog는 누군가를 반기기위한 범용적인 개념이아니라 좀 더 구체적인 의미이다.
즉, 범용적으로 쓸 수 있는 컴포넌트를 만들어놓고, 이를 특수화시켜서 컴포넌트를 사용하는 합성방법이다.
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
</FancyBorder>
);
}
function WelcomeDialog() {
return (
<Dialog
title="어서오세요!"
message="우리 사이트에 방문을 해주셔서 감사합니다." />
);
}
Containment를 사용하기위해 props.chidren을 사용하고, Specialization를 사용하기위해 직접 정의한 props를 사용한다.
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
{props.children}
/*
1. Containment를 사용하기위해 props.children추가.
이로인해 하위 컴포넌트가 Dialog 하단에 렌더링된다.
*/
</FancyBorder>
);
}
class SignUpDialog extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleSignUp = this.handleSignUp.bind(this);
this.state = {login: ''};
}
render() {
return (
/*
2. specialization을 위한 props인 title,message에 값을 넣어주고있으며
사용자로부터 닉네임을 입력받고 가입을 유도하기위해 input,button테그가있다.
이 두개의 태그는 모두 props.children으로 전달되어 dialog에 표시된다.
=> Containment
*/
<Dialog title="Mars Exploration Program"
message="How should we refer to you?">
<input value={this.state.login}
onChange={this.handleChange} />
<button onClick={this.handleSignUp}>
Sign Me Up!
</button>
</Dialog>
);
}
handleChange(e) {
this.setState({login: e.target.value});
}
handleSignUp() {
alert(`Welcome aboard, ${this.state.login}!`);
}
}
다른 컴포넌트로부터 상속을 받아서 새로운 컴포넌트를 만드는것.
그러나, 합성보다 좋은점을 찾지 못해서 추천하지않는다. 상속보다는 합성을 이용하여 컴포넌트를 만드는것을 추천한다.
복잡한 컴포넌트를 쪼개서 여러개의 컴포넌트로 만들고, 만든 컴포넌트들을 조합해서 새로운 컴포넌트를 만들자!