리액트에서는 모든 페이지가 컴포넌트로 구성되어 있고, 하나의 컴포넌트는 또 다른 여러 개의 컴포넌트의 조합으로 구성.
리액트 컴포넌트는 어떠한 속성들을 입력으로 받아서 그에 맞는 리액트 엘리먼트를 생성하여 리턴해주는 것
property : 속성, 특성
리액트 컴포넌트의 속성
컴포넌트에 전달 할 다양한 정보를 담고 있는 자바스크립트 객체
props의 중요한 특징은 읽기 전용(Read-Only).
리액트 컴포넌트는 props를 바꿀 수 없고, 같은 props가 들어오면 항상 같은 엘리먼트를 리턴!
(리액트 컴포넌트에 입력으로 들어오는 props는 자바스크립트 함수의 파라미터와 같음)
props는 컴포넌트에 전달할 다양한 정보를 담고 있는 자바스크립트 객체.
JSX를 사용하는 경우엔 카와 값으로 이루어진 키-값 쌍의 형태로 컴포넌트에 props를 넣을수 있음
function App(props){
return(
<Profile
name="소플"
introduction="안녕, 소플"
viewCount={1500}
/>
);
}
리액트 초기 버전에서는 클래스 컴포넌트를 주로 사용, 이후에 함수 컴포넌트를 개선해서 주로 사용하게 됨.
리액트의 컴포넌트를 일종의 함수라고 생각한다는 뜻
function Welcome(props){
return <h1>안녕, {props.name}</h1>;
}
ES6의 클래스라는 것을 사용해서 만들어진 형태의 컴포넌트
class Welcome extends React.Component{
render(){
return <h1>안녕, {this.props.name}</h1>;
}
}
클래스 컴포넌트는 React.Component를 상속받아서 만든다.
React.Componet라는 클래스를 상속받아서 Welcome이라는 클래스를 만들고, React.Componet를 상속받았기에 리액트 컴포넌트가 됨.
컴포넌트의 이름은 항상 대문자로 시작해야 됨
리액트는 소문자로 시작하는 컴포넌트를 DOM 태그(div
,span
)로 인식하기 때문.
function Welcome(props){
return <h1>안녕, {props.name}</h1>;
}
const element = <Welcome name="인제"/>;
ReactDOM.render(
element,
document.getElementById('root');
);
Welcome이라는 함수 컴포넌트 선언.
<Welcome name="인제"/>
라는 값을 가진 엘리먼트를 파라미터로 해서 ReactDOM.render()
를 호출.
리액트는 Welcome 컴포넌트에 {name:"인제"}
라는 props를 넣어서 호출하고 그 결과 리액트 엘리먼트가 생성.
생성된 엘리먼트는 최종적으로 ReactDOM을 통해 실제 DOM에 효과적으로 업데이트되고 브라우저를 통해 볼 수 있음.
여러개의 컴포넌트를 합쳐서 하나의 컴포넌트를 만드는 것
function Welcome(props){
return <h1>Hello, {props.name}</h1>;
}
function App(props){
return(
<div>
<Welcome name="Mike" />
<Welcome name="Steve" />
<Welcome name="Jane" />
</div>
)
}
ReactDOM.render(
<App/>,
document.getElementById('root');
);
App 컴포넌트 안에 세 개의 Welcome 컴포넌트가 있고, 각각의 Welcome 컴포넌트는 각기 다른 props를 가지고 있음.
반대로 복잡한 컴포넌트를 쪼개서 여러 개의 컴포넌트로 나누는걸 컴포넌트 추출이라고 함.
큰 컴포넌트에서 일부를 추출해서 새로운 컴포넌트를 만든다는 뜻.
//기존 Comment 컴포넌트
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>
);
}
//Avatar 컴포넌트
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
//UserInfo 컴포넌트
function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.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>
);
}
Comment 컴포넌트가 UserInfo 컴포넌트를 포함하고 있고, UserInfo 컴포넌트가 Avatar 컴포넌트를 포함하고 있는 구조.
기능 단위로 구분하는 것이 좋고, 나중에 곧바로 재사용이 가능한 형태로 추출하는 것이 좋음.
💻 소플의 처음만난 리액트