[React] prop-types으로 속성값 정의하기

권준혁·2020년 11월 1일
0

React

목록 보기
12/20
post-thumbnail

안녕하세요 prop-types에 대한 포스팅입니다.

prop-types는 Reactv15.5 이전에는 React.PropTypes였습니다. 이후에 별도의 라이브러리 prop-types로 이동했습니다.
prop-types는 속성값의 타입 정보를 정의할 때 사용하는 리액트 공식패키지입니다. 속성값의 타입을 정의하면 앱이 커짐에 따라 발생하는 예기치못한 버그를 잡을 수 있습니다. prop-types를 사용하지 않을 수도 있지만, 컴포넌트 코드의 가독성과 예기치못한 버그를 막기 위해 필수로 작성하는게 좋습니다.

prop-types패키지를 이용하면 컴포넌트에 잘못된 타입이 입력할 때 콘솔에 에러메세지를 출력합니다. 리액트가 렌더링하는 과정에서 잘못된 속성값 타입을 검사해 주기 때문입니다.
prop-types를 사용할 때 생기는 또 다른 장점은 타입 정의 자체가 훌륭한 문서가 된다는 점입니다. 컴포넌트를 일일이 들여다보지 않아도 prop-types를 코드의 윗부분에 작성해두면 속성값 정보를 쉽게 파악할 수 있습니다.

prop-types는 성능상의 이유로 개발모드에서만 동작합니다.

React공식문서 : PropTypes와 함께하는 타입확인

설치

npm i prop-types

작성방법

두 가지 방법으로 작성합니다.

컴포넌트 상단에 작성(추천)

class MyComponent extends React.Component {
    static propTypes = {
        // 여기에작성
    }
    // ...
}

컴포넌트 하단에 작성 (비추천)

class MyComponent Extends React.Component {
   // ...
}
MyComponent.propTypes = {
    // 여기에작성
}

상단에 작성하는 것을 권장하는 이유는 코드의 가독성을 높혀주기 때문입니다.


상단에 작성하는 방식으로 prop-types를 만들어보겠습니다.
부모컴포넌트를 작성하고, props를 받는 자식컴포넌트에서 prop-types를 이용해 속성값의 타입을 지정해보겠습니다.
잘 못된 타입이 속성값으로 들어왔을 경우 에러가 발생합니다.

부모컴포넌트 작성하기

import React from 'react'
import Child from "./ChildComponent";
export default class MyComponent extends React.Component {
    render () {
        return (
            <div>
                <Child name='jack'></Child>
            </div>
        )
    }
}

자식 컴포넌트

import React from 'react'
import propTypes from 'prop-types'
import Message from './Message'

export default class Child extends React.Component {
    static propTypes = {
        // 리액트 요소
        // <div>hello</div>  => 참
        // <SomeComponent/>  => 참
        // 123  => 거짓
        menu : propTypes.element,

        // 렌더 함수가 리턴할 수 있는 모든 것
        // number,string,array,element 또는 이러한 타입을 포함하고있는 배열
        // <SomeComponent /> => 참
        // 123 =>  참
        description:propTypes.node,

        // Message클래스로 생성된 모든 객체
        message : propTypes.instanceOf(Message),

        // 배열에 포함된 값중에서 하나를 만족
        // 'jone' => 참
        // 'messy' => 거짓
        name : propTypes.oneOf(['jone','mike']),

        // 배열에 포함된 타입중에서 하나를 만족
        // 123 => 참
        // 'messy' => 참
        width : propTypes.oneOfType([propTypes.number , propTypes.string]),

        // 특정 타입만 포함하는 배열
        ages : propTypes.arrayOf(propTypes.number),

        // 객체의 속성값 타입 정의
        info : propTypes.shape({
            color : propTypes.string,
            weight : propTypes.number
        }),

        // 객체에서 모든 속성값이 타입이 같은 경우
        infos : propTypes.objectOf(propTypes.number)
    }
    render () {
        return (
            <div>
            </div>
        )
    }
}

가능하면 자세하게 작성하는게 좋습니다. 당연한 이유로 propTypes.node처럼 광범위한 타입제한은 상황에 따라 쓸모가 없을 수도 있습니다.


함수로 커스텀 속성값 타입 정의하기

prop-types는 타입 정의함수를 제공합니다.
커스텀 속성값 타입을 정의하는 함수를 만들어보겠습니다.
먼저 제공되는 매개변수는 뭐가 있을지 보겠습니다.

제공되는 함수의 매개변수 확인

// 부모컴포넌트
export default class MyComponent extends React.Component {
    render () {
        return (
            <div>
                <Child name='jack' customProp='custom'></Child>
            </div>
        )
    }
}
// 자식컴포넌트
export default class Child extends React.Component {
    static propTypes = {
       // ...
            customProp : (props, ...rest) => {
            console.log({...rest})
            console.log(props)
        }
    }
}

부모컴포넌트에서 속성값을 name='jack'을, customProp='custom' 을 넘겼습니다.

▼ 콘솔에서 출력되는 매개변수확인

첫 번째 매개변수 props는 속성값들을 담은 객체리터럴을 받습니다.
두 번째 매개변수는 컴포넌트의 이름입니다.
세 번째 부터는 사실 잘 모르겠습니다 -.-
다섯 번째는 경고메세지가 나오네요

아무튼 중요한 건 사용할 수 있는 매개변수는

  • 전체속성값
  • 현재속성값이름
  • 컴포넌트이름

입니다.


함수 작성

전해지는 매개변수를 이용해서 현재 속성의 값을 참조할 수 있는 방법은

export default class Child extends React.Component {
static propTypes = {
  // ...
  customProp : (props, propsName, componentName) => {
     console.log(props[propsName])   
  }
// ...
}

이렇게 하면 현재 타입정보를 작성하려고 하는 속성값의 value를 출력할 수 있습니다.

customProp 수정 

customProp : (props, propName, componentName) => {
  if(props[propName] !== 'custom') {
     return new Error(`Invalid prop ${propName} suppied to ${componentName} ^^`)
  }
}

custom이라는 문자열이 안넘어오면 에러를 반환하게 작성했습니다.

부모컴포넌트에서 잘못된 속성값 넘겨보기

export default class MyComponent extends React.Component {
    render () {
        return (
            <div>
                <Child customProp='hello'></Child>
            </div>
        )
    }
}

▼ 직접 작성한 에러메세지가 출력됩니다.

직접 작성한 에러 메세지가 콘솔에 빨간글씨로 출력되는 걸 보니 뿌듯합니다.

defaultTypes 작성하기

defaultTypes는 말 그대로 기본으로 사용할 속성값입니다. 부모컴포넌트에서 속성값이 전달되지 않을 경우 사용할 값들인데, 이 defaultTypes를 객체로 작성하게되면, propTypes는 defaultTypes가 적용 된 뒤에 타입검사를 진행합니다. defaultTypes로 기본값으로 적용된 값들도 타입검사를 하기위해서 입니다.

    static defaultProps = {
        message : 'hi'
    }
    static propTypes = {
      message : propTypes.instanceOf(Message),
      // ...
    }

defaultProps가 적용된 후, propTypes의 타입검사를 진행합니다.
message는 instanceOf(Message)로 Message컴포넌트의 인스턴스여야 하기 때문에 에러가 예상됩니다.

▼ 에러확인

여기까지입니다. 마치겠습니다.
읽어주셔서 감사합니다!

profile
웹 프론트엔드, RN앱 개발자입니다.

0개의 댓글