출처 - 리액트를 다루는 기술(김민준 지음)
컴포넌트는 단순한 템플릿 이상의 기능을 수행한다
데이터가 주어졌을 때 이에 맞추어 UI를 만들어주고,
라이프사이클 API를 이용해 컴포넌트가 화면에서 나타날 때, 사라질 때, 변화할 때, 주어진 작업을 처리할 수 있으며,
임의 메서드를 만들어 특별한 기능을 붙여줄 수 있다
1. 클래스형 컴포넌트
컴포넌트를 선언하는 방식에는 2가지가 있다 (함수형, 클래스형)
클래스형 컴포넌트 예시
import React, { Component } from 'react';
class App extends Component {
render() {
const name = 'react';
return <div className="react">{name}</div>;
}
}
export default App;
클래스형 컴포넌트에서는 render 함수가 반드시 필요하고, 그 안에서 JSX를 반환해야 한다
클래스형 컴포넌트 vs 함수형 컴포넌트
함수형 컴포넌트의 장점은 다음과 같다
- 선언하기 쉽다
- 메모리 자원을 덜 사용한다
- 프로젝트를 완성하여 빌드 후 배포할 때도 결과물의 파일 크기가 더 작다 (성능 차이는 없다)
하지만 아래와 같은 단점이 있었다
- state와 라이프사이클 API 사용이 불가능하다
이러한 단점은 React v16.8 업데이트 이후 Hooks 기능이 도입되면서 해결되었다.
리액트 공식 매뉴얼에서는 컴포넌트를 새로 작성할 때 함수형 컴포넌트와 Hooks를 사용하도록 권장한다.
컴포넌트의 재사용
재사용 가능한 컴포넌트는 수정이 필요할 때, 여러 곳의 코드를 수정할 수고를 덜어준다.
컴포넌트는 작을수록 재사용이 쉽다. 따라서 작은 컴포넌트를 합성하여 복잡한 기능을 구축하는 것이 좋다.
컴포넌트 합성
컴포넌트 안에서 다른 컴포넌트를 참조하는 것이 가능하다
아래 코드에서는 Question 함수에서 Answer 함수를 참조한다
function Answer() {
return <h2>I am a boy!</h2>;
}
function Question() {
return (
<div>
<h1>Who are you?</h1>
<Answer />
</div>
);
}
// index.js
ReactDOM.render(<Question />, document.getElementById("root"));
컴포넌트 추출
복잡한 컴포넌트는 일부를 추출해서 분리하는 것이 가독성에도 좋고 코드 재사용에도 용이하다,
Comment 컴포넌트는 다음과 같이 복잡하게 구성되어있다
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo"> // 사용자 정보를 띄우는 UserInfo
<img className="Avatar" // 사용자 이미지를 띄우는 Avatar
src={props.author.avatarUrl} //
alt={props.author.name} //
/>
<div className="UserInfo-name">
{props.author.name}
</div> //
</div>
<div className="Comment-text"> // 댓글의 내용과 날짜를 띄우는 Comment
{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 컴포넌트에 남긴다
Comment -> UserInfo -> Avatar 구조로 컴포넌트를 분리했다
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>
);
}
코드 예시
맨 하층의 UserInfo에서는 props.user.name 처럼 2단계로 꺼내와야 한다
import React from 'react';
import './App.css';
//user의 정보(이름, 프로필사진) 출력 컴포넌트
function UserInfo(props) {
return (
<div className="UserInfo">
<div> 이름: {props.user.name}</div>
<div> 나이: {props.user.age}</div>
</div>
);
}
//코멘트 출력 컴포넌트
function Comment(props){
return(
<div className="Comment">문구: {props.text}</div>
);
}
//문구 출력 컴포넌트
function Profile(props) {
return (
<div className="Profile">
<UserInfo user={props.author} />
<Comment text={props.text} />
</div>
);
}
//데이터 저장 변수
const comment = {
text: 'I hope you enjoy learning React!',
author: {
name: '토끼',
age: '12',
},
};
const element = (
<Profile
text={comment.text}
author={comment.author}
/>
);
export default element;