상세 컨텐츠

본문 제목

[리액트를다루는기술]3장 컴포넌트

21-22/21-22 리액트 마스터

by Kimpeep 2021. 10. 11. 14:00

본문

728x90

1. 함수형 컴포넌트 vs 클래스형 컴포넌트

컴포넌트를 선언하는 방식은 함수형 컴포넌트와 클래스형 컴포넌트로 나뉩니다.

  • 클래스형 컴포넌트
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 = "리액트";
  return <div className="react">{react}</div>
}

export default App;

함수형 컴포넌트의 장점은 

  ① 클래스형 컴포넌트보다 선언하기 편하고

  ② 클래스형 컴포넌트보다 메모리 자원도 덜 사용하고

  ③ 프로젝트 완성 후 배포할 때도 결과물의 파일 크기가 더 작습니다.

 

함수형 컴포넌트의 단점은

  state 기능과 라이프 사이클 API 사용 불가능

    ⇨ Hooks 기능의 도입으로 해결되었습니다.

리액트 공식 매뉴얼에서는 함수형 컴포넌트와 Hooks를 사용하도록 권장하고 있음

2. 첫 컴포넌트 생성

  1. src 디렉터리에 MyComponent.js 파일 생성
  2. MyComponent.js 코드 작성
//MyComponent.js
import React form 'react';

const MyComponent = () => {
  return <div>나의 새롭고 멋진 컴포넌트</div>
};

export default MyComponent;

 ⭐화살표 함수

더보기

 : function 키워드 대신 () => {} 를 사용하여 함수를 표현하는 방식

 - 함수를 파라미터로 전달할 때 유용. 간결성이 큰 장점 

// 일반 함수로 표현
setTimeout(function() {
  console.log("hellow world");
}, 1000);

// 화살표 함수를 사용하여 표현
setTimeout(() => {
  console.log("hello world")
}), 1000);
// {}없으면 값을 바로 반환
const triple = (value) => value*3;

 - 일반 함수는 자신이 종속된 객체를 this로 가리키며, 화살표 함수는 자신이 종속된 인스턴스를 가리킵니다.

 

 

   3. 모듈 내보내기 및 불러오기

  • 모듈 내보내기(export)
export default MyComponent;

다른 파일에서 이 파일을 import 할 때, 위에서 선언한 MyComponent 클래스를 불러오도록 설정합니다.

  • 모듈 불러오기(import)
//App.js
import React from 'react';
import MyComponent from './MyComponent';

const App = () => {
  return <MyComponent />;
};

export default App;

import문을 이용해 MyComponent 컴포넌트를 불러와서 사용할 수 있습니다.


3. props

props : 컴포넌트 속성 설정 시 사용하는 요소

 - 부모 컴포넌트에서 설정 가능하고, 컴포넌트 자신은 읽기 전용으로만 사용 가능

 - props 값은 컴포넌트 함수의 파라미터로 받아와 사용 가능

   (JSX 내부에서 { } 기호로 감싸주면 된다)

//MyComponent.js
import React from 'react';

const MyComponent = props => {
  return <div>안녕하세요, 제 이름은 {props.name}입니다.</div>;
};

export default MyComponent;

 

//App.js
import React from 'react';
import MyComponent from './MyComponent';

const App = () => {
  return <MyComponent name="React" />;
};

export default App;

MyComponent 컴포넌트의 props 값을 지정하기 위해서는 부모 컴포넌트인 App 컴포넌트에서 지정해줘야 합니다.

클래스형 컴포넌트에서 props를 사용할 때는 render 함수에서 this.props를 조회하면 됩니다.

 

  • props 기본값 설정 : defaultProps

props 값을 따로 지정하지 않았을 때 보여줄 기본 값을 설정해줄 수 있습니다.

//MyComponent.js
import React from 'react';

const MyComponent = props => {
  return <div>안녕하세요, 제 이름은 {props.name} 입니다. </div>;
};

MyComponent.defaultProps = {
  name: '기본 이름'
};

export default MyComponent;
  • 컴포넌트 태그 사이의 내용 보여주기 : props.children
//App.js
import React from 'react';
import MyComponent from './MyComponent';

const App = () => {
  return <MyComponent>리액트</MyComponent>;
};

export default App;
//MyComponent.js
import React from 'react';

const MyComponent = props => {
  return (
    <div>
      안녕하세요, 제 이름은 {props.name}입니다.<br />
      children 값은 {props.children}
      입니다.
    </div>
  );
};

MyComponent.defaultProps = {
  name: '기본 이름'
};

export default MyComponent;
  • 비구조화 할당 문법으로 props 내부 값 바로 추출하기

비구조화 할당 문법 : 객체에서 값을 추출하는 문법 (= 구조 분해 문법)

  - 함수의 파라미터 부분에서도 사용 가능

//MyComponent.js
const MyComponent = props => {
  const { name, children } = props;
  return (
    <div>
      안녕하세요, 제 이름은 {name}입니다. <br />
      children 값은 {children}
      입니다.
    </div>
  );
};

위와 같이 props 값을 조회할 때마다 props.name, props.children처럼 props라는 키워드를 앞에 붙이지 않고도 바로 사용할 수 있게 해 줍니다.

//MyComponent.js
const MyComponent = ({ name, children }) => {
  return (
    <div>
      안녕하세요, 제 이름은 {name}입니다. <br />
      children 값은 {children}
      입니다.
    </div>
  );
};

다음과 같이 더 간결하게도 나타낼 수 있습니다.

  • propTypes를 통한 props 검증

컴포넌트의 필수 props를 지정하거나 props의 타입을 지정할 때는 propTypes를 사용합니다.

//MyComponent.js

import React from 'react';
import PropTypes from 'prop-types';

MyComponent.propTypes = {
  name : PropTypes.string,
  favoriteNumber: PropTypes.number.isRequired
};

name 값은 무조건 string 형태로 전달해야 하고, favoriteNumber 값은 number 형태로 전달해야 합니다.

isRequired를 사용하면 필수 propTypes를 설정할 수 있고, 만약 propTypes를 지정하지 않으면 Console창에 경고 메시지가 나타납니다.

 

▶ 더 많은 PropTypes 종류

더보기

array : 배열

arrayOf(다른 PropType) : 특정 PropType으로 이루어진 배열

bool : ture 혹은 false 값

func : 함수

number : 숫자

object : 객체

string : 문자열

symbol : ES6의 Symbol

node : 렌더링 할 수 있는 모든 것(숫자, 문자열, 혹은 JSX 코드

instanceOf(클래스) : 특정 클래스의 인스턴스

oneOf([‘dog’, ‘cat’]) : 주어진 배열 요소 중 값 하나

oneOfType([React.PropTypes.string, PropTypes.number]) : 주어진 배열 안의 종류 중 하나 objectOf(React.PropTypes.number) : 객체의 모든 키 값이 인자로 주어진 PropTypes인 객체

shape({ name : PropTypes.string, num:PropTypes.number}) : 주어진 스키마를 가진 객체

any : 아무 종류

 

더 자세한 정보 : https://github.com/facebook/prop-types


4. state

state : 컴포넌트 내부에서 바뀔 수 있는 값

props를 바꾸려면 부모 컴포넌트에서 바꿔주어야 하지만, state는 컴포넌트 내부에서 직접 바꿀 수 있음

리액트는 클래스형 컴포넌트의 state와 함수형 컴포넌트에서 useState 함수를 통해 사용하는 state입니다.

  • 클래스형 컴포넌트의 state
class Counter extends Component { 
  constructor(props) {
    super(props);
    this.state = {number:0, fixedNumber: 0};
  }
  render() {
    const {number} = this.state;
    return (
      <div>
        <h1>{number}</h1>
        <button onClick={() => {
          this.setState({number: number+1});
          }}> +1
        </button>
      </div>
    );
  }
}
◇ constructor 메서드
    : 컴포넌트의 생성자 메서드
    - super(props) 호출 필수
컴포넌트의 생성자 메서드 없이도 초깃값 설정은 가능하다
state = { number: 0, fixedNumber: 0};​
◇ this.setState
    : state 값을 변경하는 함수
    - state 객체 안에 여러 값이 있더라도, 인자로 전달된 객체 안의 값만 바꾸어준다.
    - this.setState를 사용하여 업데이트를 하면 상태가 비동기적으로 업데이트됩니다.
      ≫해결) 객체 대신 함수를 인자로 넣어주는 것
this.setState((prevState, props) => {
  return { ... }
})​

          prevState : 기존 상태
          props : 현재 지니고 있는 props. 필요하지 않다면 생략 가능
    - this.setState로 값 업데이트 후 특정 작업 실행 : setState의 두 번째 파라미터에 콜백 함수 등록

  • 함수형 컴포넌트의 useState

처음에 말했던 것처럼 함수형 컴포넌트에서는 state기능을 사용할 수 없었는데, 리액트 16.8부터는 Hooks 기능이 도입되어 useState함수를 사용하여 state를 사용할 수 있게 되었습니다.

import React, {useState} from 'react';
const Say = () => {
  const {message, setMessage} = useState('');
  const onClickEnter = () => setMessage('안녕하세요!');
  const onClickLeave = () => setMessage('안녕히가세요!');
  
  return (
    <div>
      <button onClick={onClickEnter}>입장</button>
      <button onClick={onClickLeave}>퇴장</button>
      <h1>{message}</h1>
    </div>
  };
};
◇ useState
    - 함수의 인자에 상태의 초깃값을 지정한다. (반드시 객체가 아니어도 상관 X)
    - 함수 호출 시 배열을 반환
        첫 번째 원소: 현재 상태
        두 번째 원소: 상태를 바꾸어주는 함수(세터 함수)
    - 3번째 줄을 보면 배열 비구조화 할당을 통해 이름을 정의해준 것을 볼 수 있다.
    - 한 컴포넌트에서 useState 여러 번 사용 가능

배열 비구조화 할당

더보기

객체 비구조화 할당과 비슷하게 배열 안에 들어있는 값을 쉽게 추출할 수 있도록 해주는 문법

배열 비구조화 할당을 통해 더 간결하게 나타낼 수 있다.

 

  • state 주의사항

❗❗ state 값 변경 시 setState 혹은 세터 함수를 사용해야 합니다.

 - 배열과 객체의 경우 : 사본에 값을 업데이트 후 setState 혹은 세터 함수를 이용

    객체에 대한 사본 - spread연산자 (...) 사용

    배열에 대한 사본 - 배열의 내장 함수 활용

 


<3장 Quiz>

Q1) 화살표 함수에서 this는 자신이 종속된 (     )를 가리킨다.

 

Q2) Props(     )에서 설정 가능하고, state(     )에서 설정할 수 있는 값이다.

 

Q3) 객체에서 내부 값을 바로 추출하는 문법으로 함수의 파라미터 부분에서도 사용 가능한 문법은?

답: (     )

 

Q4) 리액트 16.8 이후부터는 함수형 컴포넌트에서 (     )라는 함수를 사용하여 state기능을 사용할 수 있다.

 

Q5) State 값 변경 시 (     ) 혹은 (     )를 사용해야 함

 

<정답 확인>

더보기

A1) 인스턴스

A2) 부모 컴포넌트, 컴포넌트 내부

A3) 비구조화 할당 문법

A4) useState

A5) setState, 세터 함수

728x90

관련글 더보기