
2021-06-25
3장 컴포넌트
리액트를 사용하여 애플리케이션의 인터페이스를 설계할 때 사용자가 볼 수 있는 요소는 여러가지 컴포넌트로 구성되어 있다.
컴포넌트의 기능은 단순한 템플릿 이상이다. 데이터가 주어졌을 때 UI를 만들어 주는 것은 물론이고, 라이프 사이클 API를 이용해서 컴포넌트가 화면에서 변화가 일어날 때 주어진 작업을 처리할 수 있으며, 임의 메서드를 만들어 특별한 긴으을 붙여줄 수 있다.
3장에서는 클래스형 컴포넌트와 컴포넌트의 속성 값을 지닌 props와 상태 값을 지닌 state를 사용하는 방법에 대해서 알아본다.
3.1 클래스형 컴포넌트
컴포넌트를 선언하는 방식은 두 가지이다. 하나는 함수형 컴포넌트, 하나는 클래스형 컴포넌트이다.
클래스형 컴포넌트는 state 기능 및 라이프사이클 기능을 사용할 수 있다는 것과 임의 메서드를 정의할 수 있다. 또한, render 함수가 꼭 있어야하고, 그 안에서 보여 주어야 할 JSX를 반환해야 한다.
함수형 컴포넌트는 선언하기 편하고 메모리 자원도 클래스형 보다 덜 사용한다. 프로젝트를 완성해서 빌드한 후 배포할 때도 함수형 컴포넌트를 사용하는 것이 결과물의 파일 크기가 더 작다. state와 라이프사이클을 사용하지 못한다는 단점이 있지만 이는 v16.8 업데이트 이후 Hooks를 통해서 해결되었다. 리액트 공식 메뉴얼에서는 함수형 컴포넌트와 Hooks의 사용을 권장한다.
3.2 첫 컴포넌트 생성
-
ES6의 화살표 함수 문법은 함수를 파라미터로 전달할 때 유용하다. 이 문법이 기존의 function 문법을 대체할 수 없는 것은 용도가 다르기 때문이다. 무엇보다 서로 가리키고 있는 this의 값이 다르다. 일반 함수는 자신이 종속된 객체를 this로 가리키며, 화살표 함수는 자신이 종속된 인스턴스를 가리킨다.
-
rsc를 통해서 컴포넌트 코드를 간편하고 빠르게 생성할 수 있다.
import React from "react";
const MyComponent = () => {
return <div></div>;
};
export default MyComponent;
export default MyComponent
는 다른 파일에서 이 파일을 import할 때, 위에서 선언한 MyComponent 클래스를 불러오도록 한다.
import React from "react";
import MyComponent from "./MyComponent";
const App = () => {
return <MyComponent></MyComponent>;
};
export default App;
import MyComponent from "./MyComponent"
를 통해서 생성했던 MyComponent의 클래스를 불러오도록 한다.
3.3 props
-
props는 properties를 줄인 표현으로 컴포넌트 속성을 설정할 때 사용하는 요소이다. props 값은 해당 컴포넌트를 불러와 사용하는 부모 컴포넌트에서 설정 가능하다.
-
defaultProps를 사용하면 props의 값을 따로 지정하지 않았을 때 보여주는 기본값을 설정할 수 있다.
Component.defaultProps = { value : ‘default value’};
- 리액트 컴포넌트를 사용할 때 컴포넌트 태그 사이의 내용을 보여주는 props는 children이다.
import React from "react";
const MyComponent = ({ name, children }) => {
return (
<div>
안녕하세요, 제 이름은 {name} 입니다. <br />
태그 안의 내용 값은 {children} 입니다.
</div>
);
};
export default MyComponent;
위와 같이 객체에서 값을 추출하는 문법인 비구조화 할당을 할 수 있다. 이는 함수의 파라미터 부분에서도 사용할 수 있다. 만약 함수의 파라미터가 객체라면 그 값을 바로 비구조화 해서 사용한다. 여기서 name과 children은 props 객체의 요소들로 객체를 파라미터로 받을 때는 { }
를 사용하도록 한다.
- porpTypes를 통해서 props의 타입을 지정해준다. defaultProps를 지정하는 것과 비슷하다.
import PropTypes from "prop-types";
Mycomponent.propTypes = {
name: PropTypes.string,
favoriteNumber: PropTypes.number.isRequired,
};
위와 같이 PropTypes.number.isRequired
를 통해서 필수로 들어가는 값을 지정할 수 있다. PropType 종류 보기
- propsTypes를 통해서 큰 규모의 프로젝트를 진행 시, 개발 능률을 올릴 수 있다.
3.4 state
-
state는 컴포넌트 내부에서 바뀔 수 있는 값을 의미한다. props는 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하는 값이며, 컴포넌트는 자신의 해당 props를 읽기 전용으로만 사용할 수 있다. props를 바꾸려면 부모 컴포넌트에서 바꾸어 주어야 한다. java에서 객체지향 프로그래밍을 할 때, 인스턴스를 생성하고 그 인스턴스에 파라미터 값을 주는데 그 값을 지정하는 것과 비슷하다. 하지만 state는 전달 받은 값을 바꿀 수 있도록 하는 것과 같다.
-
props는 컴포넌트에 전달 받은 값, state는 컴포넌트 내에서 변경할 수 있는 값
Counter.js
import React from "react";
class Counter extends React.Component {
constructor(props) {
super(props);
// state 초깃값 설정하기
this.state = {
number: 0,
};
}
render() {
const { number } = this.state; // state를 조회할 때는 this.state로 합니다.
return (
<div>
<h1>{number}</h1>
<button
onClick={() => {
this.setState({ number: number + 1 });
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
-
클래스형 컴포넌트에서
constructor
를 작성할 때는 반드시super(props)
를 호출해주어야 한다. 이 함수가 호출되면 현재 클래스형 컴포넌트가 상속받고 있는 리액트의 Component클래스가 지닌 생성자를 호출하게 된다. 컴포넌트의 state는 객체 형식이어야 한다. state와 lifecycle 설명 바로가기 -
this.setState
를 이용해서 state 값을 업데이트할 때는 상태가 비동기적으로 업데이트 된다.setState
는 두 번째 파라미터로 callback함수를 등록하여 작업할 수 있다. -
16.8 이전 버전에서는 함수형 컴포넌트에서 state를 사용할 수 없었다. 하지만 useState라는 함수를 사용해서 함수형 컴포넌트에서도 state를 사용할 수 있게 되었다.
배열의 비구조화 할당은 아래와 같은 예시로 설명 가능하다.
const array = [1, 2];
const one = array[0];
const two = array[1];
const array = [1, 2];
const [one, two] = array;
- useState 함수의 인자에는 상태의 초깃값을 넣어 준다. 클래스형 컴포넌트의 state는 객체 형태를 넣어 주어야 하지만 useState에서는 반드시 객체가 아니어도 상관없다.
Say.js
import React, { useState } from "react";
const Say = () => {
const [message, setMessage] = useState("");
const onClickEnter = () => setMessage("안녕하세요!");
const onClickLeave = () => setMessage("안녕히계세요!");
const [color, setColor] = useState("black");
return (
<div>
<button onClick={onClickEnter}>입장</button>
<button onClick={onClickLeave}>퇴장</button>
<h1 style=>{message}</h1>
<button style= onClick={() => setColor("red")}>
빨간색
</button>
<button style= onClick={() => setColor("green")}>
초록색
</button>
<button style= onClick={() => setColor("blue")}>
파란색
</button>
</div>
);
};
export default Say;
함수를 호출하면 배열이 반환되는데, 배열의 첫 번째 원소는 현재 상태이고, 두 번째 원소는 상태를 바꾸어 주는 함수이다. 이 함수를 setter 함수라고 한다. 배열의 비구조화 할당을 통해 이름을 자유롭게 설정 가능하다. useState는 한 컴포넌트에서 여러 번 사용해도 상관없다.
3.5 state를 사용할 때 주의할 점
- state 값을 바꾸어야 할 때는 setState 혹은 useState를 통해 전달받은 세터 함수를 사용해야 한다.
- 배열이나 객체를 업데이트 할 때는 사본을 만들고 사본에 업데이트를 한 후, 사본의 상태를 setState 혹은 setter 함수를 통해 업데이트 한다.
- 객체의 사본을 만들 때는 spread 연산자
...
을 사용한다.