3장. 컴포넌트(1)
3.1 클래스형 컴포넌트
컴포넌트 선언 방식
- 함수형 컴포넌트
- 클래스형 컴포넌트
클래스형 컴포넌트
import React, {Component} from 'react'
class App extends Component{
render(){
const name = 'react';
return <div className="react">{name}</div>;
}
}
export default App;
- 클래스형 컴포넌트는 state 기능 및 라이프사이클 기능을 사용할 수 있고, 임의 메서드를 정의할 수 있다.
- render 함수가 꼭 있어야 하고, 그 안에서 보여 주어야 할 JSX를 반환해야 한다.
함수형 컴포넌트
import React from 'react';
import './App.css';
function App() {
const name = 'react';
return <div className="react">{name}</div>;
}
export default App;
- 클래스형 컴포넌트보다 선언하기 훨씬 편하고, 메모리 자원도 덜 사용한다.
- 프로젝트를 완성하여 빌드한 후 배포할 때도 함수형 컴포넌트를 사용하는 것이 결과물의 크기가 더 작다.
- state와 라이프사이클 API의 사용이 불가능하다 → 리액트 v16.8 업데이트 후 Hooks라는 기능이 도입되면서 해결됌
※ 컴포넌트를 작성할 때 함수형 컴포넌트와 Hooks를 사용하도록 권장하고 있음
▷ 함수에서 클래스로 변환하기
- React.Component를 확장하는 동일한 이름의 ES6 class를 생성합니다.
- render()라고 불리는 빈 메서드를 추가합니다.
- 함수의 내용을 render() 메서드 안으로 옮깁니다.
- render() 내용 안에 있는 props를 this.props로 변경합니다.
- 남아있는 빈 함수 선언을 삭제합니다.
3.2 첫 컴포넌트 생성
1) src 디렉터리에서 MyComponent.js 파일 생성
컴포넌트를 만드려면 컴포넌트 코드를 선언해야 한다.
VS Code 왼쪽 사이드바 파일 목록 중 src 디렉터리 우 클릭 → 새 파일 메뉴 선택 → MyComponent.js 입력
2) 코드 작성하기
Mycomponent.js
import React from 'react';
const MyComponent = () =>
return <div>나의 새롭고 멋진 컴포넌트</div>
};
export default Mycomponent;
▶ ES6의 화살표 함수
() => {} 는 ES6에 새로 도입된 화살표 문법 함수이다. 그렇다고 해서 기존의 function을 이용한 함수 선언 방식과는 사용 용도가 조금 다르므로 아예 대체하지는 않는다. 이 문법은 주로 함수를 파라미터로 전달할 때 유용하게 쓰인다.
따로 { }를 열어 주지 않으면 연산한 값을 그대로 반환한다는 의미이다.
----function 사용----
setTimeout(function(){
console.log('hello world');
},1000);
-----화살표 함수 사용-----
setTimeout(() =>{
console.log('hello world')
}),1000);
서로 가리키고 있는 this 값이 다르게 나타난다. 일반함수는 자신이 종속된 객체를 this로 가리키고, 화살표 함수는 자신이 종속된 인스턴스(부모함수)를 가리킨다.
function BlackDog() {
this.name='흰둥이';
return {
name: '검둥이';
bark: function() {
console.log(this.name + ': 멍멍!');
}
}
}
const blackDog = new BlackDog();
blackDog.bark(); // 검둥이: 멍멍!
function WhiteDog() {
this.name = '흰둥이';
return {
name: '검둥이',
bark: () => {
console.log(this.name + ': 멍멍!');
}
}
}
const whiteDog = new WhiteDog();
whiteDog.bark(); // 흰둥이: 멍멍!
- 객체: 소프트웨어 세계에 구현할 대상
- 클래스: 객체를 구현하기 위한 설계도
- 인스턴스: 설계도에 따라 소프트웨어 세계에 구현된 실체
3) 모듈 내보내기 및 불러오기
3.1) 모듈 내보내기(export)
export dafault MyComponent;
→ 다른 파일에서 이 파일을 import할 때, 위에서 선언한 MyComponent 클래스를 불러오도록 설정한다.
3.2) 모듈 불러오기(import)
App.js
import React from 'react';
import MyComponent from './MyComponent'; // 우리가 만든 MyComponent 컴포넌트를 불러옴
const App = () => {
return <MyComponent />;
};
export default App;
→ 우리가 만든 MyComponent 컴포넌트를 불러온다.
3.3 props
props는 properties를 줄인 표현으로 컴포넌트 속성을 설정할 때 사용하는 요소이다. props 값은 해당 컴포넌트를 불러와 사용하는 부모 컴포넌트에서 설정할 수 있다.
1) JSX 내부에서 props 렌더링
해당 컴포넌트에서 name이라는 props를 렌더링하도록 설정하자. props 값은 컴포넌트 함수의 파라미터로 받아 와서 사용할 수 있고, props를 렌더링할 때는 JSX 내부에서 { } 기호로 감싸주면 된다.
MyComponent.js
import React from 'react';
const MyComponent = props => {
return <div>안녕하세요, 제 이름은 {props.name}입니다.</div>;
};
export default MyComponent;
→ MyComponent 컴포넌트를 수정하여 해당 컴포넌트에서 name이라는 props를 렌더링하도록 설정하였다.
2) 컴포넌트를 사용할 때 props 값 저장하기
App 컴포넌트에서 MyComponent의 props 값을 지정해보자.
App.js
import React from 'react';
import MyComponent from './MyComponent'; // 우리가 만든 MyComponent 컴포넌트를 불러옴
const App = () => {
return <MyComponent name="React" />;
};
export default App;
결과 출력 → 안녕하세요, 제 이름은 React 입니다.
3) props 기본값 설정: defaultProps
방금 설정한 name 값을 지우고 다시 수정해보자.
(...)
return <MyComponent />;
(...)
결과 출력 → 안녕하세요, 제 이름은 입니다.
위와 같이 props 값을 따로 지정하지 않았을 때 보여주는 기본 값이 defaultProps이다. 이 값을 설정하는 방법은 다음과 같다.
import React from 'react';
const MyComponent = props => {
return <div>안녕하세요, 제 이름은 {props.name}입니다.</div>;
};
MyComponent.defaultProps = {
name: '기본 이름'
};
export default MyComponent;
결과 출력 → 안녕하세요, 제 이름은 기본 이름 입니다.
4) 태그 사이의 내용을 보여 주는 children
children은 리액트 컴포넌트를 사용할 때 컴포넌트 태그 사이의 내용을 보여주는 props이다.
App.js
import React from 'react';
import MyComponent from './MyComponent'; // 우리가 만든 MyComponent 컴포넌트를 불러옴
const App = () => {
return <MyComponent>리액트</MyComponent>
};
export default App;
위 코드에서 MyComponent 태그 사이에 작성한 문자열을 MyComponent 내부에서 보여 주려면 props.children 값을 보여 주어야 한다.
MyComponent.js
import React from 'react';
const MyComponent = props => {
return (
<div>안녕하세요, 제 이름은 {props.name}입니다.<br />
children 값은 {props.children}
입니다.
</div>
);
};
MyComponent.defaultProps = {
name: '기본 이름'
};
export default MyComponent;
////결과 출력////
안녕하세요, 제 이름은 기본 이름 입니다.
children 값은 리액트입니다.
5) 비구조화 할당 문법을 통해 props 내부 값 출력하기
ES6의 비구조화 할당 문법을 사용하여 내부 값을 바로 추출하는 방법을 알아보자.
MyComponent.js (method #1)
import React from 'react';
const MyComponent = props => {
const { name, children } = props;
return (
<div>안녕하세요, 제 이름은 {name}입니다.<br />
children 값은 {children}
입니다.
</div>
);
};
MyComponent.defaultProps = {
name: '기본 이름'
};
export default MyComponent;
방금 사용한 객체에서 값을 추출하는 문법을 비구조화 할당(구조 분해 문법)이라고 부르고, 함수의 파라미터 부분에서도 사용할 수 있다.
MyComponent.js (method #2) ★이 방법 권장!
import React from 'react';
const MyComponent = ({ name, children }) => {
return (
<div>안녕하세요, 제 이름은 {name}입니다.<br />
children 값은 {children}
입니다.
</div>
);
};
MyComponent.defaultProps = {
name: '기본 이름'
};
export default MyComponent;
6) propTypes를 통한 prop 검증
- 컴포넌트의 필수 props를 지정하거나 props의 타입을 지정할 때는 propTypes를 사용한다.
- propTypes를 사용하려면 코드 상단에 import 구문을 사용하여 불러와야 한다.
- 컴포넌트의 propTypes를 지정하는 방법은 defaultProp을 설정하는 것과 비슷하다.
MyComponent.js
import React from 'react';
import PropTypes from 'prop-types';
const MyComponent = ({name,children}) = >{
return (...);
};
MyComponent.defaultProps = {
name: '기본 이름'
};
MyComponent.propTypes = {
name : PropTypes.string
};
export default MyComponent;
→ name 값은 무조건 문자열 형태로 전달해야 함을 뜻한다.
propTypes를 지정할 때 뒤에 isRequired를 붙여 주면 propTypes를 지정하지 않았을 때 경고 메세지를 띄울 수 있다.
MyComponent.js
import React from 'react';
import PropTypes from 'prop-types';
const MyComponent = ({ name, favoriteNumber, children }) => {
return (
<div>
안녕하세요, 제 이름은 {name} 입니다. <br />
children 값은 {children}
입니다.
<br />
제가 좋아하는 숫자는 {favoriteNumber} 입니다.
</div>
);
};
MyComponent.defaultProps = {
name = '기본 이름';
};
MyComponent.propTypes = {
name : PropTypes.string,
favoriteNumber: PropTypes.number.isRequired
// favoriteNumber가 설정되어있지 않으면 경고메세지 출력
};
export default MyComponent;
만약 favoriteNumber가 부모컴포넌트에 설정되어있지 않다면 아래 코드를 수정해보자.
App.js
import React from 'react';
import PropTypes from 'prop-types';
const App = () => {
return (
<MyComponent name="React" favoriteNumber={1}>
리액트
</MyComponent>
);
};
export default App;
▶ 더 많은 PropTypes 종류
- array
- arrayOf (다른 PropType) : 특정 PropType으로 이루어진 배열
- bool
- func
- number
- object
- string
- symbol : ES6의 symbol
- node : 렌더링할 수 있는 모든 것 (숫자, 문자열, JSX코드, children)
- instanceof (클래스) : 특정 클래스의 인스턴스
- oneOf ([ 'dog', 'cat' ]) : 주어진 배열 요소 값 중 하나
- oneOfType ([React.PropTypes.string, PropTypes.number]) : 주어진 배열 안의 종류 중 하나
- objectOf (React.PropTypes.number) : 객체의 모든 키 값이 주어진 PropType인 객체
- ...
7) 클래스형 컴포넌트에서 props 사용하기
- 클래스형 컴포넌트에서 props를 사용할 떄는 render 함수에서 this.props를 조회하면 된다.
- defaultProps와 propTypes은 똑같은 방식으로 설정할 수 있다.
MyComponent.js
import React, {Component} from 'react';
import PropTypes from 'prop-types';
class MyComponent extends Component {
render(){
const{ name, favoriteNumber, children } = this.props; // 비구조화 할당
return (
<div>
안녕하세요. 제 이름은 {name}입니다.<br/>
children 값은 {children}입니다.
</div>
);
}
}
MyComponent.defaultProps = {
name: '기본 이름'
};
MyComponent.propTypes = {
name : Proptypes.string,
favoriteNumber: Proptypes.number.isRequired
};
export default MyComponent;
클래스형 컴포넌트에서 defaultProps와 propTypes를 설정할 때 class 내부에서 지정하는 방법도 있다.
import React, {Component} from 'react';
import PropTypes from 'prop-types';
class MyComponent extends Component {
static defaultProps = {
name : '기본 이름'
};
static propTypes = {
name: PropTypes.string,
favoriteNumber: PropTypes.number.isRequired
};
render() {
const { name, favoriteNumber, children } = this.props // 비구조화 할당
return (...);
}
}
export default MyComponent;