일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 리스트
- 실전 자바 고급 1편
- java network
- java
- java socket
- Docker
- 알고리즘
- Kubernetes
- 스레드
- Thread
- container
- 컨테이너
- 자바
- 스레드 제어와 생명 주기
- 쿠버네티스
- 동시성
- Java IO
- 인프런
- filewriter filereader
- LIST
- 자바 입출력 스트림
- 멀티 쓰레드
- 쓰레드
- 시작하세요 도커 & 쿠버네티스
- 자료구조
- 자바 io 보조스트림
- Collection
- 김영한
- 도커 엔진
- 도커
- Today
- Total
쌩로그
리액트를 다루는 기술 - 03. 컴포넌트 본문
목록
- 포스팅 개요
- 본론
2-1. 클래스형 컴포넌트
2-2. 첫 컴포넌트 생성
2-3. props
2-4. state
2-5. state를 사용할 때 주의 사항 - 요약
1. 포스팅 개요
해당 포스팅은 리액트를 다루는 기술의 03장 컴포넌트
를 학습하며 정리한 포스팅이다.
2. 본론
컴포넌트의 기능은 단순한 템플릿 이상이다.
데이터가 주어졌을 때 이에 맞추어 UI를 만들어 준다.
라이프 사이클 API를 이용하여 컴포넌트가 화면에서 나타날 때, 사라질 때 등 변화가 일어날 때 주어진 작업들을 처리할 수 있다.
임의 메서드를 만들어 특별한 기능을 붙여줄 수 있다.
2-1. 클래스형 컴포넌트
컴포넌트를 선언하는 방식은 두 가지이다.
- 함수형 컴포넌트.
- 클래스형 컴포넌트
import '../ClassInsteaedClassNameApp.css'
import {Component} from "react";
class ClassionalComponent extends Component {
render() {
const name = 'react';
return <div className="react">{name}</div>
}
}
export default ClassionalComponent;
클래스형 컴포넌트와 함수형 컴포넌트의 차이점
- 클래스형 컴포넌트의 경우 state 기능 및 라이프사이클 기능을 사용할 수 있다.
- 임의 메서드를 정의할 수 있다.
- 클래스형 컴포넌트에서는
render
함수가 꼭 있어야 한다.- 이 안에서는 보여주어야할 JSX를 반환해야 한다.
함수형 컴포넌트의 장점
- 클래스형 컴포넌트보다 선언하기 훨씬 편하다.
- 메모리 자원 사용이 클래스형 컴포넌트보다 덜 하다.
- 프로젝트를 완성하여 빌드한 후 배포할 때 함수형 컴포넌트를 사용하는 것이 결과물의 파일 크기가 더 작다.
- (번외) 성능과 파일 크기 면에서는 사실상 별 차이가 없다.
함수형 컴포넌트의 단점
- state와 라이프 사이클 API의 사용이 불가능하다.
- 리액트 v16.8 업데이트 이후 Hooks라는 기능이 도입되면서 해결되었다.
- Hook은 8장에서 나온다.
- 리액트 공식 매뉴얼에서는 컴포넌트를 새로 작성할 때 함수형 컴포넌트와 Hook를 사용하도록 권장하고 있다.
2-2. 첫 컴포넌트 생성
ES6의 화살표 함수
ES6 문법에서 함수를 표현하는 새로운 방식
주로 함수를 파라미터로 전달할 때 유용하다.
기존의 function 문법과 대체할 수 없는 것은 용도가 다르다.
- 서로 가리키는 this 값이 다르다.
일반함수(function)은 자신이 종속된 객체를 this로 가리킨다.
화살표 함수는 자신이 종속된 인스턴스를 가리킨다.
화살표 함수는 값을 연산하여 바로 반환해야 할 때 사용하면 가독성을 높일 수 있다.
function twice(value) { return value * 2; } const triple = (value) => value * 3;*
함수형 컴포넌트를 선언할 때 function 키워드를 사용하는 것과 화살표 함수 문법을 사용하는 것 간에는 큰 차이가 없다.
- 화살표 함수를 사용하는 것이 좀 더 간결하다.
- 때문에 책에서는 함수형 컴포넌트를 만들 때 화살표 함수 문법을 사용한다.
- 화살표 함수를 사용하는 것이 좀 더 간결하다.
모듈 내보내기(export)
- 모듈 내보내는 방법은 다음과 같다.
export default MyComponent;
- 모듈 불러오기(import)
- 모듈을 불러오는 방법은 다음과 같다.
import React from 'react';
...
2-3. props
props는 properties를 줄인 표현으로 컴포넌트 속성을 설정할 때 사용하는 요소이다.
props는 해당 컴포넌트를 불러와 사용하는 부모 컴포넌트에서 설정할 수 있다.
props 값은 컴포넌트 함수의 파라미터로 받아 와서 사용할 수 있다.
- 렌더링시에는 JSX 내부에서
{ }
기호로 감싸주면 된다.
- 렌더링시에는 JSX 내부에서
props 기본값 설정 : defaultProps
import '../ClassInsteaedClassNameApp.css' // 모듈 불러오기
const PropsFunctionalComponent = props => {
return <div>안녕하세요 제 이름은 {props.name}입니다.</div>;
};
PropsFunctionalComponent.defaultProps = {
name: '기본 이름'
}
export default PropsFunctionalComponent; // 모듈 내보내기
태그 사이의 내용을 보여주는 children
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<ChildrenComponent>리액트</ChildrenComponent>
</React.StrictMode>);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<ChildrenComponent>리액트</ChildrenComponent>
</React.StrictMode>);

비구조화 할당 문법을 통해 props 내부 값 추출하기
import React from "react";
const DestructuringAssignmentComponent = props => {
const {name, children} = props;
return (
<div>
안녕하세요, 제 이름은 {name}입니다. <br/>
children 값은 {children}
입니다.
</div>
);
};
DestructuringAssignmentComponent.defaultProps = {
name: '기본 이름',
}
export default DestructuringAssignmentComponent;
위의 코드를 더 간단히
import React from "react";
// 이 부분이 바뀜.
// const DestructuringAssignmentComponent = props => {
// const {name, children} = props;
const DestructuringAssignmentComponent = ({name, children}) => {
return (
<div>
안녕하세요, 제 이름은 {name}입니다. <br/>
children 값은 {children}
입니다.
</div>
);
};
DestructuringAssignmentComponent.defaultProps = {
name: '기본 이름',
}
export default DestructuringAssignmentComponent;
propTypes를 통한 props 검증
- 컴포넌트의 필수 props를 지정하거나 props의 타입(type)을 지정할 때는 propTypes를 사용한다.
- 지정하는 방법은 defaultProps를 설정하는 것과 비슷하다.
- 사용하려면 상단에
import
로 불러와야 한다.
import React from "react";
import PropTypes from "prop-types";
const PropTypesComponent = ({name, children}) => {
return (...);
}
사용 예시
import React from "react";
import PropTypes from "prop-types";
const PropTypesComponent = ({name, children}) => {
return (
<div>
안녕하세요, 제 이름은 {name}입니다. <br/>
children 값은 {children}
입니다.
</div>
);
};
PropTypesComponent.defaultProps = {
name: '기본 이름',
}
PropTypesComponent.propTypes = {
name: PropTypes.string,
}
export default PropTypesComponent;
- 위와 같이 설정해주면 name 값은 무조건 문자열(string) 형태로 전달해야 된다.
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<PropTypesComponent name={3}>리액트</PropTypesComponent>
</React.StrictMode>);
이렇게 해서 name에 숫자를 주면 다음과 같은 에러가 발생한다.

name을 아래와 같이 주면 오류가 나오지 않는다.
name={"3"} // or
name="React"
isRequired를 사용하여 필수 propTypes 설정
- propTypes를 지정하지 않았을 때
isRequired
를 사용하여 경고 메세지를 띄워줄 수 있다.
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<IsRequiredComponent name={"3"}>리액트</IsRequiredComponent>
</React.StrictMode>);
import PropTypes from "prop-types";
const IsRequiredComponent = ({name, favoriteNumber, children}) => {
return (
<div>
안녕하세요, 제 이름은 {name}입니다. <br/>
children 값은 {children}
입니다.
<br/>
제가 좋아하는 숫자는 {favoriteNumber}입니다.
</div>
);
};
IsRequiredComponent.defaultProps = {
name: '기본 이름',
}
IsRequiredComponent.propTypes = {
name: PropTypes.string,
favoriteNumber: PropTypes.number.isRequired,
}
export default IsRequiredComponent;
현재 favoriteNumber를 넘기지 않고 있으므로 다음과 같은 에러를 발견할 수 있다.

따라서 다음과 같이 props를 넘겨주면 된다.
<IsRequiredComponent name="React" favoriteNumber={1}>
리액트
</IsRequiredComponent>

오류 사라짐.
PropTypes 종류(참고용)
페이스북 깃허브 prop-types에서 확인 가능하다.
클래스형 컴포넌트에서 props 사용하기
import React, { Component } from "react";
import PropTypes from "prop-types";
class UserPropsByComponent extends Component {
render() {
const { name, favoriteNumber, children } = this.props; // 비구조화 할당
return (
<div>
안녕하세요, 제 이름은 {name}입니다. <br/>
children 값은 {children}
입니다.
<br/>
제가 좋아하는 숫자는 {favoriteNumber}입니다.
</div>
);
}
}
UserPropsByComponent.defaultProps = {
name: '기본 이름',
};
UserPropsByComponent.propTypes = {
name: PropTypes.string,
favoriteNumber: PropTypes.number.isRequired
};
export default UserPropsByComponent;
class 내부에서 설정하는 방법은 다음과 같다.
import React, { Component } from "react";
import PropTypes from "prop-types";
class InnerUserPropsByComponent extends Component {
static defaultProps = {
name: '기본 이름',
}
static propTypes = {
name: PropTypes.string,
favoriteNumber: PropTypes.number.isRequired
};
render() {
const { name, favoriteNumber, children } = this.props; // 비구조화 할당
return (
<div>
안녕하세요, 제 이름은 {name}입니다. <br/>
children 값은 {children}
입니다.
<br/>
제가 좋아하는 숫자는 {favoriteNumber}입니다.
</div>
);
}
}
export default InnerUserPropsByComponent;
2-4. state
리액트에서 state는 컴포넌트 내부에서 바뀔수 있는 값을 의미한다.
- props는 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하는 값이다.
- 컴포넌트 자신은 해당 props를 읽기 전용으로만 사용할 수 있다.
- props를 바꾸려면 부모 컴포넌트에서 바꾸어 주어야 한다.
- props를 전달받은 컴포넌트에서는 값을 직접 바꿀 수 없다.
리액트에는 두 종류의 state가 있다.
- 클래스형 컴포넌트가 지니고 있는 state
- 함수형 컴포넌트에서
useState
라는 함수를 통해 사용하는 state
클래스형 컴포넌트의 state
import {Component} from "react";
class ClassionalStateComponent extends 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을 통해 버튼이 클릭되었을 때 호출할 함수를 지정한다.
onClick={() => {
// this.setState를 사용하여 state에 새로운 값을 넣을 수 있다.
this.setState({ number: number + 1})
}}
>
+1
</button>
</div> )
}
}
export default ClassionalStateComponent;
- 컴포넌트에 state를 설정할 때는
constructor
메서드를 작성하여 설정한다.constructor
메서드는 컴포넌트의 생성자 메서드이다.- 클래스형 컴포넌트에서
constructor
메서드를 작성할 때는 반드시super(props)
를 호출해야 한다.- 이 함수가 호출되면 현재 클래스형 컴포넌트가 상속하고 있는 리액트의 Component 클래스가 지닌 생성자 함수를 호출해준다.
- 클래스형 컴포넌트에서
- 이후
this.state
값에 초깃값을 설정해주었다. - 컴포넌트의 state는 객체 형식이어야 한다.
constructor(props) {
super(props);
// state의 초깃갑 설정
this.state = {
number: 0
};
}
다음은 render()
함수다.
render() {
const {number} = this.state; // state를 조회할 때는 this.state로 조회한다.
return (
<div>
<h1>{number}</h1>
<button // onClick을 통해 버튼이 클릭되었을 때 호출할 함수를 지정한다.
onClick={() => {
// this.setState를 사용하여 state에 새로운 값을 넣을 수 있다.
this.setState({ number: number + 1})
}}
>
+1
</button>
</div> )
}
- render 함수에서 현재 state를 조회할 때는 this.state를 조회하면 된다.
- button안에
onClick
이라는 값을 props로 넣어주었다.- 버튼이 클랙될 때 호출시킬 함수를 설정할 수 있게 해준다.
- 이를 "이벤트를 설정한다"고 한다.

import {Component} from "react";
class ClassionalStateComponent extends Component {
constructor(props) {
super(props);
// state의 초깃갑 설정
this.state = {
number: 0,
fixedNumber: 0
};
}
render() {
const {number, fixedNumber } = this.state; // state를 조회할 때는 this.state로 조회한다.
return (
<div>
<h1>{number}</h1>
<h2>바뀌지 않는 값 : {fixedNumber}</h2>
<button // onClick을 통해 버튼이 클릭되었을 때 호출할 함수를 지정한다.
onClick={() => {
// this.setState를 사용하여 state에 새로운 값을 넣을 수 있다.
this.setState({ number: number + 1})
}}
>
+1
</button>
</div> )
}
}
export default ClassionalStateComponent;
onClick 함수에 fixedNumber 를 주진 않았다.
this.setState
함수는 인자로 전달된 객체 안에 들어있는 값만 바꿔준다.

state를 constructor에서 꺼내기
이전에 초깃값을 지정하기 위해 constructor
메서드를 선언했다.
다른 방식으로도 초깃값을 설정할 수 있다.
import {Component} from "react";
class ConstructorComponent extends Component {
state = {
number: 0,
fixedNumber: 0
};
render() {
const {number, fixedNumber } = this.state; // state를 조회할 때는 this.state로 조회한다.
return (
<div>
<h1>{number}</h1>
<h2>바뀌지 않는 값 : {fixedNumber}</h2>
<button // onClick을 통해 버튼이 클릭되었을 때 호출할 함수를 지정한다.
onClick={() => {
// this.setState를 사용하여 state에 새로운 값을 넣을 수 있다.
this.setState({ number: number + 1})
}}
>
+1
</button>
</div> )
}
}
export default ConstructorComponent;
(결과는 동일하다.)
앞으론 constructor
가 아닌 state
를 사용할 때 이 방식을 이용한다.
this.setState에 객체 대신 함수 인자 전달하기
this.setState
를 사용하여 state 값을 업데이트할 때는 상태가 비동기적으로 업데이트된다.
그래서 다음과 같이 onClick()
내부에 코드를 this.setState
를 두 번 호출하더라도 숫자는 1씩 더해진다.
onClick={() => {
this.setState({ number: number + 1})
this.setState({number: this.state.number + 1})
}}
this.setState
를 사용한다고 해서 state 값이 바로 바뀌지 않는다.
해결책은 this.setState
를 사용할 때 객체 대신에 함수를 인자로 넣어주는 것이다.
this.setState((prevState, props) => {
return {
// 업데이트하고 싶은 내용
}
})
- prevState : 기존상태
- props : 현재 지니고 있는 props
업데이트 과정에서 props가 필요하지 않다면 생략해도 된다.
다음과 같이 사용할 수 있다.
onClick={() => {
this.setState(prevState => {
return {
number: prevState.number + 1
};
});
// 위의 코드와 아래 코드는 완전히 똑같은 기능을 한다.
// 아래 코드는 함수에서 바로 객체를 반환한다는 의미(return 문 생략)
this.setState(prevState => ({
number: prevState.number + 1
}));
}}
- 화살표 함수에서 값을 바로 반환하고 싶다면 코드 블록
{ }
을 생략하면 된다. onClick
에서 두 번째로this.setState
함수를 사용할 때는 화살표 함수에서 바로 객체를 반환하도록 했기 때문에prevState => ({ })
와 같은 형태로 코드가 이루어진다.
this.setState가 끝난 후 특정 작업 실행하기
setState
를 사용하여 값을 업데이트하고 난 다음에 특정 작업을 하고 싶을 때는 setState
의 두 번째 파라미터로 콜백(callback) 함수를 등록하여 작업을 처리할 수 있다.
import {Component} from "react";
class CallbackComponent extends Component {
state = {
number: 0,
fixedNumber: 0
};
render() {
const {number, fixedNumber } = this.state; // state를 조회할 때는 this.state로 조회한다.
return (
<div>
<h1>{number}</h1>
<h2>바뀌지 않는 값 : {fixedNumber}</h2>
<button onClick={() => {
this.setState(
{
number: number + 1
},
() => {
console.log('방금 setState가 호출되었습니다.');
console.log(this.state);
}
)
}}
>
+1
</button>
</div> )
}
}
export default CallbackComponent;

함수형 컴포넌트에서 useState 사용하기
- 리액트 16.8 이전에는 함수형 컴포넌트에서 state를 사용할 수 없었다.
- 16.8 이후부터
useState
함수를 사용하여 함수형 컴포넌트에서 state를 사용할 수 있게 되었다.- 해당 장에서는
useState
만 배워본다.
- 해당 장에서는
배열 비구조화 할당
const array = [1, 2];
const one = array[0];
const two = array[1];
위의 코드는 아래와 같이 할 수 있다.
const array = [1, 2];
const [one, two] = array;
useState 사용하기
import {useState} from "react";
const SayComponent = () => {
const [message, setMessage] = useState('');
const onClickEnter = () => setMessage('안녕하세요!');
const onClickLeave = () => setMessage('안녕히 가세요!');
return (
<div>
<button onClick={onClickEnter}>입장</button>
<button onClick={onClickLeave}>퇴장</button>
<h1>{message}</h1>
</div> )
}
export default SayComponent;
useState 함수의 인자에는 상태의 초깃값을 넣어준다.
- 클래스형 컴포넌트에서의 state 초깃값은 객체 형태를 넣어주어야 했다.
- useState에는 반드시 객체가 아니어도 상관없다.
- 즉, 값의 형태는 자유다.
함수를 호출하면 배열이 반환된다.
- 배열의 첫 번째 원소는 현재 상태
- 배열의 두 번째 원소는 상태를 바꾸어주는 함수
- 함수를 세터(setter) 함수라고 한다.
message, setMessage라고 이름을 설정했지만, test, setText라고 이름을 자유롭게 바꾸어도 상관없다.
import SayComponent from "./SayComponent";
const AppComponent = () => {
return <SayComponent/>
}
export default AppComponent;
- 입장

- 퇴장

한 컴포넌트에서 useState 여러 번 사용하기
- useState는 한 컴포넌트에서 여러 번 사용해도 상관없다.
import React, { useState } from "react";
const MauyUsingUseState = () => {
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={{color}}>{message}</h1>
<button style={{color: 'red'}} onClick={() => setColor('red')}>
빨간색
</button>
<button style={{color: 'green'}} onClick={() => setColor('green')}>
초록색
</button>
<button style={{color: 'blue'}} onClick={() => setColor('blue')}>
파란색
</button>
</div> );
}
export default MauyUsingUseState;


2-5. state를 사용할 때 주의 사항
- 클래스형 컴포넌트든 함수형 컴포넌트든 state를 사용해야 할 때
setState
혹은useState
를 통해 전달받은 세터 함수를 사용해야 한다. - 다음은 잘못된 코드 예시다.
// 클래스형 컴포넌트에서
this.state.number = this.state.number + 1;
this.state.array = this.array.push(2);
this.state.object.value = 5;
// 함수형 컴포넌트에서
const [object, setObject] = useState({ a: 1, b: 1 });
object.b = 2
배열이나 객체를 업데이트 해야할 때는 배열이나 객체 사본을 만들고, 그 사본에 값을 업데이트한 후, 그 사본의 상태를 setState
혹은 세터 함수를 통해 업데이트해야 한다.
사본을 만들어서 업데이트하는 예시는 다음과 같다.
// 객체
const object = {a: 1, b: 2, c: 3};
const nextObject = { ...object, b: 2}; // 사본을 만들어서 b값만 덮어 쓰기
// 배열
const array = [
{ id: 1, value: true },
{ id: 2, value: true },
{ id: 3, value: false }
];
let nextArray = array.concat({ id: 4 }); // 새 항목 추가
nextArray.filter(item => item.id !== 2); // id가 2인 항목 제거
nextArray.map(item => (item.id ===1 ? { ...item, value: false } : item)); // id가 1인 항목의 value를 false로 설정
- 객체에 대한 사본을 만들 때는
spread
연산자라 불리는...
을 사용하여 처리한다. - 배열에 대한 사본을 만들 때는 배열의 내장 함수들을 활용한다.
3. 요약
컴포넌트를 만들어서 내보내고 불러오는 방법을 배웠다.
props 및, state를 사용하는 방법을 배웠다.
props는 부모 컴포넌트가 설정하고,
state는 컴포넌트 자체적으로 지닌 값으로 컴포넌트 내부에서 업데이트 할 수 있다.
props를 사용한다고 해서 무조건 값이 고정적인 것은 아니다.
- 부모 컴포넌트의 state를 자식 컴포넌트의 props로 전달하고, 자식 컴포넌트에서 특정 이벤트가 발생할 때 부모 컴포넌트의 메서드를 호출하면 props도 유동적으로 사용할 수 있다.
'Front > React' 카테고리의 다른 글
리액트를 다루는 기술 - 06. 컴포넌트 반복 (0) | 2024.04.10 |
---|---|
리액트를 다루는 기술 - 05. ref - DOM에 이름 달기 (0) | 2024.04.10 |
리액트를 다루는 기술 - 04. 이벤트 핸들링 (0) | 2024.04.08 |
리액트를 다루는 기술 - 02. JSX (0) | 2024.03.26 |
리액트를 다루는 기술 - 01. 리액트 시작 (0) | 2024.03.26 |