ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React Advanced] Typechecking With PropTypes
    프로그래밍/웹 2018. 4. 6. 21:48
    Typechecking With PropTypes.md

    Typechecking With PropTypes

    리액트 버전 v15.5부터 React.Proptypesprop-types 라이브러리로 이동 되었습니다.

    하위 버전에서는 codemod script를 사용해서 변환하세요.

    프로젝트의 크기가 커지면 커질 수록 타입 체크와 관련된 수많은 버그들이 쏟아져 나올 것이다. FlowTypeScript를 이용해서 타입 체크를 수행할 수도 있겠지만, 리액트에서는 빌트인 타입체크 툴을 제공한다. 컴포넌트 내에서 사용하는 props에 대해서 타입체크를 수행하기 위해서는 propTypes라는 특수한 속성을 사용하면 된다.

     
    x
    import PropTypes from 'prop-types';
    class Greeting extends React.Component {
      render() {
        return (
          <h1>Hello, {this.props.name}</h1>
        );
      }
    }
    Greeting.propTypes = {
      name: PropTypes.string
    };

    PropTypes는 컴포넌트에서 사용하는 데이터의 유효성을 검사하는데 사용되는 다양한 종류의 유효성 검사 툴을 가지고 있다. 위의 예제에서는 PropTypes.string을 사용하고 있다. 유효하지 않은 값이 props를 통해 전달되면 자바스크립트 콘솔에서 경고문을 볼 수 있을 것이다. 실제 앱 구동시에는 성능상의 이유로 인해서 동작하지 않고, 개발 중에만 propTypes가 동작한다.

    PropTypes

     
    x
    import PropTypes from 'prop-types';
    MyComponent.propTypes = {
      // You can declare that a prop is a specific JS type. By default, these
      // are all optional.
      optionalArray: PropTypes.array,
      optionalBool: PropTypes.bool,
      optionalFunc: PropTypes.func,
      optionalNumber: PropTypes.number,
      optionalObject: PropTypes.object,
      optionalString: PropTypes.string,
      optionalSymbol: PropTypes.symbol,
      // Anything that can be rendered: numbers, strings, elements or an array
      // (or fragment) containing these types.
      optionalNode: PropTypes.node,
      // A React element.
      optionalElement: PropTypes.element,
      // You can also declare that a prop is an instance of a class. This uses
      // JS's instanceof operator.
      optionalMessage: PropTypes.instanceOf(Message),
      // You can ensure that your prop is limited to specific values by treating
      // it as an enum.
      optionalEnum: PropTypes.oneOf(['News', 'Photos']),
      // An object that could be one of many types
      optionalUnion: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.number,
        PropTypes.instanceOf(Message)
      ]),
      // An array of a certain type
      optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
      // An object with property values of a certain type
      optionalObjectOf: PropTypes.objectOf(PropTypes.number),
      // An object taking on a particular shape
      optionalObjectWithShape: PropTypes.shape({
        color: PropTypes.string,
        fontSize: PropTypes.number
      }),
      // You can chain any of the above with `isRequired` to make sure a warning
      // is shown if the prop isn't provided.
      requiredFunc: PropTypes.func.isRequired,
      // A value of any data type
      requiredAny: PropTypes.any.isRequired,
      // You can also specify a custom validator. It should return an Error
      // object if the validation fails. Don't `console.warn` or throw, as this
      // won't work inside `oneOfType`.
      customProp: function(props, propName, componentName) {
        if (!/matchme/.test(props[propName])) {
          return new Error(
            'Invalid prop `' + propName + '` supplied to' +
            ' `' + componentName + '`. Validation failed.'
          );
        }
      },
      // You can also supply a custom validator to `arrayOf` and `objectOf`.
      // It should return an Error object if the validation fails. The validator
      // will be called for each key in the array or object. The first two
      // arguments of the validator are the array or object itself, and the
      // current item's 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.'
          );
        }
      })
    };

    위의 예제는 종류별로 지원 가능한 PropTypes를 사용하는 예제이다.

     

    Requiring Single Child

     
    xxxxxxxxxx
    import PropTypes from 'prop-types';
    class MyComponent extends React.Component {
      render() {
        // This must be exactly one element or it will warn.
        const children = this.props.children;
        return (
          <div>
            {children}
          </div>
        );
      }
    }
    MyComponent.propTypes = {
      children: PropTypes.element.isRequired
    };

    위의 에제처럼 PropTypes.element 속성을 사용하여 반드시 한개의 하위 엘리먼트가 전달 되도록 체크할 수도 있다.

     

    Default Prop Values

    defaultProps 속성을 사용하면 props에 할당 될 기본 값을 정의할 수도 있다.

     
    xxxxxxxxxx
    class Greeting extends React.Component {
      render() {
        return (
          <h1>Hello, {this.props.name}</h1>
        );
      }
    }
    // Specifies the default values for props:
    Greeting.defaultProps = {
      name: 'stranger'
    };
    // Renders "Hello, Stranger":
    ReactDOM.render(
      <Greeting />,
      document.getElementById('example')
    );

    Babel등을 사용하여 transform-class-properties를 이용하면, defaultProps를 컴포넌트의 static 속성으로 정의 할 수도 있다. 아직 리액트의 기본 기능으로 정의 되지 않았으므로, 실제로 사용하려면 웹에 뿌리기 이전에 컴파일 단계를 거쳐야 한다. 예제는 아래와 같다.

     
    xxxxxxxxxx
    class Greeting extends React.Component {
      static defaultProps = {
        name: 'stranger'
      }
      render() {
        return (
          <div>Hello, {this.props.name}</div>
        )
      }
    }

    위의 두 예제는 this.props.name에 아무 입력이 없을 경우 'stranger'가 저장되도록 하는 코드이다. propTypes의 타입 체킹은 defaultProps가 할당 된 이후에 발생하므로, defaultProps의 내용이 잘 못 작성 되었을 경우에는 타입체킹이 수행된다.

Designed by Tistory.