컴포넌트를 통해 UI를 재사용 가능한 개별적인 여러 조각으로 나눌 수 있고, 개념적으로 JavaScript 함수와 유사하다.
props
라고 하는 임의의 입력을 받은 후, 화면에 어떻게 표시되는지를 기술하는 React Element를 반환한다. 이는 함수 컴포넌트와 클래스 컴포넌트로 나뉜다.
리액트에서 제공하는 React.Component 클래스를 상속해서 만들 수 있다.
class Welcome extends React.Component{
render(){
return <h1>hello, {this.props.name}</h1>;
}
}
UI가 어떻게 표기될 것인지를 정의하는 render()
함수를 구현해야 한다.(필수)
state
(상태)가 있고 그 상태에 따라서 컴포넌트가 주기적으로 업데이트되어야 할 때 사용한다.
state
(상태)란?
- UI를 표기하기 위한 데이터를 담을 수 있는 오브젝트를 말함
- state가 변경되면 리액트가 알아서 render함수를 호출해 업데이트 된 내용을 사용자에게 보여준다.
lifecycle methods가 있다.
생성 단축키: rcc
state 및 lifecycle methods는 다른 포스팅에서 자세히 다룬다.
컴포넌트를 정의하는 가장 간단한 방법으로 아래와 같이 JSX를 반환하는 함수를 정의하면 된다.
function Welcome(props){
return <h1>Hello, {props.name}</h1>;
}
<리액트 16.8버전 이전>
state
)가 없이 props만 보여주면 되거나, 둘다 없는 정적인 컴포넌트를 표기할 때 사용한다.rsi
<React Hook 도입 이후>
useState
, useEffect
.. 등을 통해 class component의 state와 lifecycle methods와 같은 기능 구현이 가능해졌다.자세한 건 다른 포스팅에서 다룬다.
React Element는 사용자 정의 컴포넌트로 나타낼 수 있다.
<Welcome name="Sara" onClick={handleClick}/>;
props는 컴포넌트 밖에서 주어지는 데이터(객체)로, React가 사용자 정의 컴포넌트(여기선 <Welcome/>
)를 발견하면 해당 컴포넌트에 단일 객체로 전달하는 것을 말한다.
위의 예시처럼 부모 컴포넌트에서 Welcome 컴포넌트를 사용하면 name
, onClick
에 해당하는 것들이 props
오브젝트로 묶여서 Welcome
컴포넌트로 전달된다. 그러면 Welcome 안에서 this.props.name
, this.props.onClick
으로 각각 전달된 'Sara'와 this.handleClick
함수를 접근해 사용할 수 있게 된다.
props는 읽기 전용 으로 컴포넌트의 자체 props를 수정해서는 안된다. 반드시 순수 함수처럼 동작해야 한다.
🔍순수함수란?
아래와 같이 입력값을 변경하지 않고 항상 동일한 입력값에 대해 동일한 결과를 반환하는 함수를 말함function sum(a,b){ return a+b; }
function Welcome(props){
return <h1>Hello, {props.name}</h1>;
}
const element =<Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);
<Welcome name="Sara" />
엘리먼트로 ReactDOM.render()
를 호출{name:'Sara'}
를 props로 하여 Welcome
컴포넌트를 호출Welcome
컴포넌트는 <h1>Hello, Sara</h1>
를 반환<h1>Hello, Sara</h1>
와 일치하도록 DOM을 효율적으로 업데이트❗ 주의: 컴포넌트 이름은 항상 "대문자"로 시작
React는 소문자로 시작하는 컴포넌트를 DOM 태그로 처리한다.
e.g.<div/>
→ HTML div 태그,<Welcome />
→ 컴포넌트
컴포넌트는 자신의 출력에 다른 컴포넌트를 참조할 수 있다.
e.g. Welcome
을 여러 번 렌더링하는 App
컴포넌트
(일반적으로 새 React 앱은 최상위에 단일 App
컴포넌트를 가지고 있음)
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
컴포넌트를 여러 개의 작은 컴포넌트로 나누는 것을 말한다.
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
이 컴포넌트는 author
, text
, date
을 props로 받은 후 웹 사이트의 코멘트를 나타낸다. 여기서 Avater
를 추출해 보자.
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
Avatar
는 자신이 Comment
내에서 렌더링 된다는 것을 알 필요가 없다. 따라서 props의 이름을 author
에서 더욱 일반화된 user
로 변경하자.
❗ props의 이름은 사용될 context가 아닌 "컴포넌트 자체의 관점" 에서 짓는 것을 권장한다.
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<Avatar user={props.author} />
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
이러한 방법으로 컴포넌트들을 추출해내면 상위 컴포넌트가 보다 단순해 질수 있다.
function Comment(props) {
return (
<div className="Comment">
<UserInfo user={props.author} />
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
이렇듯 재사용 가능한 컴포넌트들을 만들어 놓으면 더 큰 앱에서 작업할 때 두각을 나타낸다. UI 일부가 여러 번 사용되거나(Button, Panel, Avatar), UI 일부가 자체적으로 복잡한(App, FeedStory, Comment)경우에는 별도의 컴포넌트로 만드는 게 좋다.