[React] 3. 컴포넌트

Uicheon·2023년 6월 3일
0

리액트

목록 보기
3/3
post-thumbnail

3. 컴포넌트

컴포넌트의 기능은 단순 템플렛 이상

  • 데이터 주어졌을 때 이에 맞춘 UI
  • 라이프사이클 API => 화면에서 나타날 때, 사라질 때, 변화가 일어날 때 작업 처리
  • 임의 메서드 만들어 특별한 기능을 붙이기
  • 속성 값 props / 상태값 state

3.1 클래스형 컴포넌트

계속 봐왔던 App 컴포넌트는 함수 컴포넌트

function App() {
  const name = "react";
  return <div className="react">{name}</div>;
}
export default App;

컴포넌트를 선언하는 방식은 두가지다.

  • 함수 컴포넌트
  • 클래스 컴포넌트

클래스형 컴포넌트는 다음과 같이 생겼다.

class App extends Component {
  render() {
    const name = "react";
    return <div className="react">{name}</div>;
  }
}

클래스형 컴포넌트와 함수형 컴포넌트 차이

  • state 기능
  • 라이프 사이클 기능 사용
  • 임의 메서드 정의

클래스형 컴포넌트는

  • render 함수가 필수
  • 그 안에 보여주어야 할 JSX 반환

그럼 언제 어떤걸 사용하나?

  • 함수형 장점
    • 선언이 편하다
    • 메모리 적게 사용
    • 빌드/배포 후에도 함수 컴포넌트가 결과 파일 크기가 작음
  • 함수형 단점
    • state 사용 안됨
    • 라이프사이클 API 사용 안됨
    • 그러나 Hooks 기능 도입후 극복

리액트 공식문서도 함수 컴포넌트 + hooks 사용을 권장한다
그러나 클래스형 컴포넌트가 사라지는건 아님

3.2 컴포넌트 생성

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

export default MyComponent;

function 키워드 대신에 () => {}를 사용했다. 이는 ES6의 화살표 함수 문법

화살표 함수는 사용용도가 다르다. 주로 함수를 파라미터로 전달할 때 유용하다

기존 function을 대체할 수 없다. 왜냐하면 용도가 다르기 때문
무엇보다 가르키는 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: function(){
      console.log( this.name + ': 멍멍!');
  }
 }
}
const whiteDog = new WhiteDog();
whiteDog.bark(); // 흰둥이: 멍멍

function() 사용시는 검둥이가,() => 는 흰둥이가 나타난다.
일반 함수는 자신이 종속된 객체를 this로 가르키며, 화살표 함수는 자신이 종속된 인스턴스를 가르킨다.
또한 값을 연산하여 바로 반환 할 때 사용해도 가독성을 높인다

function twice(value){
  return value*2;
}

const triple = (value) => value*3;

따로 {}를 열어주지 않으면 값을 그대로 반환한다는 의미이다.

3.2.3 모듈 내보내기 및 불러오기

3.2.3.1 모듈 내보내기(export)

다음 코드는 뭘까?

export default MyComponent;

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

3.2.3.2 모듈 불러오기(import)

그럼 App 컴포넌트에서 MyComponent를 사용하려면 다음과 같이 사용한다.

import MyComponent from "./MyComponent";

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

3.3 props

  • props는 properties의 줄임
  • 컴포넌트 속성을 설정
  • 해당 컴포넌트를 불러와 사용하는 부모 컴포넌트(현재는 App 컴포넌트가 된다)에서 설정할 수 있다.

3.3.1 JSX 내부에서 props 렌더링

MyComponent가 name이라는 props를 렌더링 해보자.

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

// MyComponent.js
const MyComponent = (props) => {
  return <div> 내 이름은 {props.name} 입니다.</div>;
};

3.3.3 props 기본값 설정: defaultProps

만약 App.js의 ;에서 name 프로퍼티를 지우면 어떻게 될까?
name값을 지정하지 않았기에 내 이름은 입니다.가 출력된다.
property값을 지정하지 않았을 때 보여줄 기본 값을 defaultProps로 설정할 수 있다.

const MyComponent = (props) => {
  return <div> 내 이름은 {props.name} 입니다.</div>;
};

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

export default MyComponent;

3.3.4 태그 사이의 내용을 보여주는 children

리액트 컴포넌트 사용할 때 컴포넌트 태그 사이의 내용을 보여주는 props를 children이다

//App.js
const App = () => {
  return <MyComponent>태그 안 내용</MyComponent>;
};

//MyComponent.js
const MyComponent = (props) => {
  return (
    <div>
      내 이름은 {props.name} 입니다.
      <br /> children 값은{props.children} 입니다.
    </div>
  );
};

3.3.5 비구조화 할당 문법을 통해 props 내부 값 추출하기

비구조화 할당/구조 분해 문법이라고 부른다.

const MyComponent = props => {
  const { name, children } = props;
  return (
    <div>
      내 이름은 {name} 입니다.
      <br /> children 값은{children} 입니다.
    </div>
  );
};

함수의 파라미터 부분에서도 사용할 수 있다.
props를 사용한다면, 바로 비구조화 할당 문법을 사용하자.

//개선된 버전
const MyComponent = ({ name, children }) => {
  return (
    <div>
      내 이름은 {name} 입니다.
      <br /> children 값은{children} 입니다.
    </div>
  );
};

3.3.6 propTypes를 통한 props 검증

컴포넌트의 필수 props를 지정하거나, props의 타입을 지정할 때는 propTypes를 사용한다. defaultProps와 비슷하다.

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

만약 name prop에 숫자를 넣는다면

const App = () => {
  return <MyComponent name={3}>태그 안 내용</MyComponent>;
};

다음과 같은 오류가 발생한다

failed prop type: Invalid prop name of type number supplied to MyComponent, expected string.

3.3.6.1 isRequired를 사용하여 필수 propTypes 설정

propTypes를 지정하지 않았을 때 경고 메시지를 띄울 수 있다.
propTypes를 지정할 때 뒤에 isRequired를 붙여주면 된다.

const MyComponent = ({ name, favoriteNumber, children }) => {
  return (
    <div>
      내 이름은 {name} 입니다.
      <br /> children 값은{children} 입니다.
      <br /> 제가 좋아하는 숫자는 {favoriteNumber}입니다.
    </div>
  );
};

...

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

마찬가지로 다음 오류가 발생한다

Failed prop type: The prop favoriteNumber is marked as required in MyComponent, but its value is undefined.

3.3.6.2 더 많은 PropTypes 종류

  • array
  • arrayOf : 특정 PropType으로 이루어진 배열 ex) arrayOf(PropTypes.number) 숫자배열
  • bool
  • func
  • number ,obejct, string, symbol
    = node: 렌더링할 수 있는 모든 것 (숫자, 문자열, JSX, children도 node다)
    ...

3.3.7 클래스형 컴포넌트에서 props 사용하기

클래스형 컴포넌트에서 props를 사용할 때는 render 함수에서 this.props를 조회하면 된다. defaultProps, propTypes는 똑같이 설정한다.
다음과 같이 바꿀 수 있다.

class MyComponent extends Component {
  render() {
    const { name, favoriteNumber, children } = this.props;
    return (
      <div>
        내 이름은 {name} 입니다.
        <br /> children 값은{children} 입니다.
        <br /> 제가 좋아하는 숫자는 {favoriteNumber}입니다.
      </div>
    );
  }
}

defaultProps와 propTypes를 꼭 사용해야 하나요?
필수 사항은 아니지만, 큰 프로젝트에 협업을 해야한다면 쓰자

3.4 state

리액트에서 state는 컴포넌트 내부에서 바뀔 수 있는 값을 의미한다.

  • props
    • 부모 컴포넌트가 설정
    • 해당 컴포넌트는 props를 읽기 전용으로만 사용
    • props를 바꾸려면 부모에서 바꿔야함
    • 즉, MyComponent에서는 전달받은 name값을 직접 바꿀 수 없음

리액트는 두가지 state가 있다.

  • 클래스형 컴포넌트가 지니는 state
  • 함수 컴포넌트에서 useState라는 함수를 통해 사용하는 state

3.4.1 클래스형 컴포넌트의 state

//Counter.js
import { Component } from "react";

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      number: 0,
    };
  }
  render() {
    const { number } = this.state;
    return (
      <div>
        <h1>{number}</h1>
        <button
          onClick={() => {
            this.setState({ number: number + 1 });
          }}
        >
          +1
        </button>
      </div>
    );
  }
}

export default Counter;

클래스형 컴포넌트에 state를 설정할 때는 constructor 메서드를 작성하여 설정한다.
컴포넌트 생성자 메서드에서 반드시 super(props)를 호출해 주어야 한다. 이 함수가 호출되면 현재 클래스형 컴포넌트가 상속하고 있는 Component 클래스가 지닌 생성자 함수를 호출해 준다.

profile
컨셉입니다~

0개의 댓글