본문 바로가기

React

[react] propTypes - 리액트에서 type을 확인하는 방법

앱이 커짐에 따라서, 타입검사를 하면 많은 에러를 잡을 수 있다. 자바스크립트의 유연한 타입 특성상 에러가 많이 날 수 있는데, 이를 보완하기 위해 나온 언어가 타입스크립트이다. 그런데 꼭 이 언어를 사용하지 않더라도, 리액트도 내장된 타입검사 기능을 가지고 있다. 오늘은 이것을 알아보자. 

 

proptypes는 부모로부터 전달받은 prop의 데이터 type을 검사한다. 자식 컴포넌트에서 명시해 놓은 데이터 타입과 부모로부터 넘겨받은 데이터타입이 일치하지 않으면 콘솔에 에러 경고문이 띄워진다. 아래의 예시 코드를 보자. 

 

우선, prop-types 패키지에서 PropTypes 객체를 임포트해야한다. (리액트 내장기능이기 때문에 따로 설치할 필요는 없다. )

import PropTypes from 'prop-types';

Greeting.propTypes = {
  name: PropTypes.string
};

const Greeting = ({ name }) => {
    return (
      <h1>Hello, {name}</h1>
    );
}

위 코드에서 부모에게서 받은 name이라는 props가 string 형태가 아니라 숫자, 함수 또는 객체 등 다른 형태면 콘솔에 에러 메시지가 출력된다. 

 

 

이런 식으로 propTypes를 활용해 코드를 작성하면, 타입에러를 줄일 수 있다는 장점이 있지만, 또 다른 장점이 있다. 타입을 정의함으로써 읽기 좋은 코드를 만들 수 있다는 것이다. 타입을 코드상에서 지정해주기 전에는 부모로부터 전달받는 props의 값들을 확인하기 위해서, 코드의 로직을 뜯어보지 않으면 안된다. 하지만, propTypes를 활용하면 바로바로 타입을 확인할 수 있고, 코드의 흐름을 파악하기가 더욱 쉬워진다. 

 

아래는 propTypes에서 사용할 수 있는 여러가지 타입들을 설명하고 있다.(리액트 공식문서 참조)

import PropTypes from 'prop-types';
 
MyComponent.propTypes = {
  // prop가 특정 JS 형식임을 선언할 수 있습니다.
  // 이것들은 기본적으로 모두 선택 사항입니다.
  optionalArray: PropTypes.array,
  optionalBool: PropTypes.bool,
  optionalFunc: PropTypes.func,
  optionalNumber: PropTypes.number,
  optionalObject: PropTypes.object,
  optionalString: PropTypes.string,
  optionalSymbol: PropTypes.symbol,
 
  // 랜더링 될 수 있는 것들은 다음과 같습니다.
  // 숫자(numbers), 문자(strings), 엘리먼트(elements), 또는 이러한 타입들(types)을 
  // 포함하고 있는 배열(array) (혹은 배열의 fragment)
  optionalNode: PropTypes.node,
 
  // React 엘리먼트.
  optionalElement: PropTypes.element,
 
  // React 엘리먼트 타입 (ie. MyComponent)
  optionalElementType: PropTypes.elementType,
 
  // prop가 클래스의 인스턴스임을 선언할 수 있습니다.
  // 이 경우 JS's instanceof 연산자를 사용합니다.
  optionalMessage: PropTypes.instanceOf(Message),
 
  // 열거형(enum)으로 처리하여 prop가 특정 값들로 제한되도록 할 수 있습니다.
  optionalEnum: PropTypes.oneOf(['News', 'Photos']),
 
  // 여러 종류중 하나의 종류가 될 수 있는 객체
  optionalUnion: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.number,
    PropTypes.instanceOf(Message)
  ]),
 
  // 특정 타입의 행렬
  optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
 
  // 특정 타입의 프로퍼티 값들을 갖는 객체
  optionalObjectOf: PropTypes.objectOf(PropTypes.number),
 
  // 특정 형태를 갖는 객체
  optionalObjectWithShape: PropTypes.shape({
    color: PropTypes.string,
    fontSize: PropTypes.number
  }),
 
  // An object with warnings on extra properties
  optionalObjectWithStrictShape: PropTypes.exact({
    name: PropTypes.string,
    quantity: PropTypes.number
  }),
 
  // 위에 있는 것 모두 `isRequired`와 연결하여 prop가 제공되지 않았을 때
  // 경고가 보이도록 할 수 있습니다.
  requiredFunc: PropTypes.func.isRequired,
 
  // 모든 데이터 타입이 가능한 값
  requiredAny: PropTypes.any.isRequired,
 
  // 사용자 정의 유효성 검사기를 지정할 수도 있습니다.
  // 검사 실패 시에는 에러(Error) 객체를 반환해야 합니다.
  // `oneOfType`안에서는 작동하지 않으므로 `console.warn` 혹은 throw 하지 마세요.
  customProp: function(props, propName, componentName) {
    if (!/matchme/.test(props[propName])) {
      return new Error(
        'Invalid prop `' + propName + '` supplied to' +
        ' `' + componentName + '`. Validation failed.'
      );
    }
  },
 
  // `arrayOf` 와 `objectOf 에 사용자 정의 유효성 검사기를 적용할 수 있습니다.
  // 검사 실패 시에는 에러(Error) 객체를 반환해야 합니다.
  // 유효성 검사기는 배열(array) 혹은 객체의 각 키(key)에 대하여 호출될 것입니다.
  // 유효성 검사기의 첫 두 개의 변수는 배열 혹은 객체 자신과 현재 아이템의 키입니다.
 
  customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
    if (!/matchme/.test(propValue[key])) {
      return new Error(
        'Invalid prop `' + propFullName + '` supplied to' +
        ' `' + componentName + '`. Validation failed.'
      );
    }
  })
};r