리액트 주요개념 - Component와 Props

컴포넌트는 JavaScript 함수와 유사합니다. props(임의의 입력)을 받은 후 React Element(화면에 어떻게 표시되는지 기술)반환합니다.
함수 컴포넌트와 클래스 컴포넌트
컴포넌트를 정의하는 가장 간단한 벙법: JavaScript 함수 작성
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
위의 함수는 데이터를 가진 객체 인자를 받은 후 React 엘리먼트를 반환하기 때문에 유효한 React 컴포넌트입니다.
이러한 컴포넌트는 JavaScript 함수이기 때문에 함수 컴포넌트라고 호칭합니다.
또한, ES6 class를 사용하여 컴포넌트를 정의할 수 있는데 React 관점에서 볼 때 위, 아래 두 가지 유형의 컴포넌트는 동일합니다.
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
컴포넌트 렌더링
지금까지 DOM 태그만을 사용해 React 엘리먼트를 나타냈는데 React 엘리먼트는 사용자 정의 컴포넌트로도 나타낼 수 있습니다.
const element = <Welcome name="Sara" />;
React가 사용자 정의 컴포넌트로 작성한 엘리먼트를 발견하면 JSX 속성과 자식을 해당 컴포넌트에 단일 객체로 전달하며 이 객체를 props라고 합니다.
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()를 호출.
- React는 {name: 'Sara'}를 props로 하여 Welcome 컴포넌트를 호출
- Welcome 컴포넌트는 결과적으로 <h1>Hello, Sara</h1> 엘리먼트 반환
- React DOM은 <h1>Hello, Sara</h1> 엘리먼트와 일치하도록 DOM을 효율적으로 업데이트
컴포넌트의 이름은 항상 대문자!!!로 시작합니다.
저는 소문자로 쓰고 실행이 안되서 한참 찾았어요...ㅜㅜ
컴포넌트 합성
컴포넌트는 자신의 출력에 다른 컴포넌트를 참조할 수 있습니다.
=> 모든 세부 단계에서 동일한 추상 컴포넌트를 사용할 수 있음을 의미
//Welcome을 여러 번 렌더링하는 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 formatDate(date) {
return date.toLocaleDateString();
}
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>
);
}
const comment = {
date: new Date(),
text: 'I hope you enjoy learning React!',
author: {
name: 'Hello Kitty',
avatarUrl: 'https://placekitten.com/g/64/64',
},
};
ReactDOM.render(
<Comment
date={comment.date}
text={comment.text}
author={comment.author}
/>,
document.getElementById('root')
);
위의 comment 컴포넌트는 author, text, date를 props로 받은 후 소셜 미디어 웹 사이트의 코멘트를 나타냅니다.
해당 컴포넌트는 구성요소들이 모두 중첨 구조로 이루어져 있어 변경하기 어려울 수 있고 각 구성 요소를 개별적으로 재사용하기도 힘듭니다. 따라서 몇 컴포넌트를 추출하는 것이 좋습니다.
우선 Avatar를 추출합니다.
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
Avatar 컴포넌트는 자신이 Comment 내에서 렌더링 된다는 것을 알 필요가 없기 때문에 props의 이름을 author에서 더욱 일반화된 user로 변경하였습니다.
props의 이름은 사용될 context가 아닌 컴포넌트 자체의 관점에서 짓는 것을 권장!
그 결과 Comment가 조금 단순해진 것을 확인할 수 있습니다.
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>
);
그 다음 UserInfo 컴포넌트 추출
function UserInfo(props) {
return(
<div className='UserInfo'>
<Avatar user={props.author} />
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
);
}
그 결과 Comment 간소화
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 일부가 여러 번 사용되거나 UI 일부가 자체적으로 복잡한 경우에는 별도의 컴포넌트로 만드는게 좋습니다!
props는 읽기 전용입니다.
함수 컴포넌트나 클래스 컴포넌트 모두 컴포넌트의 자체 props를 수정해서는 안됩니다.
function sum(a, b) {
return a + b;
}
위와 같은 함수를 순수 함수라고 합니다. 입력값을 바꾸지 않고 항상 동일한 입력값에 대해 동일한 결과를 반환하기 때문입니다.
그러나 아래의 함수는 자신의 입력값을 변경하기 때문에 순수 함수라고 할 수 없습니다.
function withdraw(account, amount) {
account.tatal -= amount;
}
React에서 반드시 지켜야 할 규칙은
모든 React 컴포넌트는 자신의 props를 다룰 때 반드시 순수 함수 처럼 동작해야 한다.
입니다.