3.2 Проверка типов с PropTypes

Внимание! React.PropTypes является устаревшим начиная с React v15.5. Пожалуйста, вместо этого используйте prop-types библиотеку.

Разработчики предоставляют скрипт codemode для автоматизации преобразования.

С ростом вашего приложения, вы можете получить много багов с проверками типов. Для некоторых приложений вы можете использовать JavaScript расширения, такие как Flow или TypeScript , чтобы проверять типы во всем вашем приложении. Но даже если вы их не используете, React имеет несколько встроенных возможностей по проверке типов. Чтобы запустить проверку типов для свойств компонента, вы можете назначить специальное свойство propTypes:


Код
    
  import PropTypes from 'prop-types';

  class HelloWorld extends React.Component {
    render() {
      return (
        <h1>Привет, {this.props.name}</h1>
      );
    }
  }

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

PropTypes экспортирует множество валидаторов, которые могут использоваться, чтобы убедиться, что данные, которые вы получаете, являются валидными. В данном примере мы используем PropTypes.string. Когда свойству предоставляется не валидное значение, будет показано предупреждение в JavaScript консоли. По соображениям производительности, propTypes работает только в режиме разработки.


3.2.1 PropTypes

Здесь показан пример, который отображает различные предоставленные валидаторы:


Код
    
  import PropTypes from 'prop-types';

  MyComponent.propTypes = {
    // Вы можете объявить, что свойство является определенным JS примитивом.
    // По умолчанию они все необязательны.
    myOptionalArray: PropTypes.array,
    myOptionalBool: PropTypes.bool,
    myOptionalFunc: PropTypes.func,
    myOptionalNumber: PropTypes.number,
    myOptionalObject: PropTypes.object,
    myOptionalString: PropTypes.string,
    myOptionalSymbol: PropTypes.symbol,



    // Все, что может быть отрисовано: числа, строки, элементы или массив
    // (или фрагмент), содержащий эти типы
    myOptionalNode: PropTypes.node,

    // React-элемент.
    myOptionalElement: PropTypes.element,

    // Вы также можете обьявить, что свойство является экземпляром класса.
    // Для этого используется instanceof оператор.
    myOptionalMessage: PropTypes.instanceOf(Message),

    // Вы можете гарантировать, что ваше свойство ограничено определенным
    // набором значений, представленных перечислением
    myOptionalEnum: PropTypes.oneOf(['News', 'Photos']),

    // Объект, который может иметь один из перечисленых типов
    myOptionalUnion: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.number,
      PropTypes.instanceOf(Message)
    ]),

    // Массив объектов определенного типа
    myOptionalArrayOf: PropTypes.arrayOf(PropTypes.number),

    // Объект со значениями свойств определенного типа
    myOptionalObjectOf: PropTypes.objectOf(PropTypes.number),

    // Объект, приобретающий определенную форму
    myOptionalObjectWithShape: PropTypes.shape({
      color: PropTypes.string,
      fontSize: PropTypes.number
    }),

    // Вы можете связать любой из вышеперечисленых валидаторов с 'isRequired', чтобы убедиться,
    // что предупреждение показывается, если значение свойства не предоставлено
    myRequiredFunc: PropTypes.func.isRequired,

    // Значение произвольного типа данных
    myRequiredAny: PropTypes.any.isRequired,

    // Вы можете задать и собственный валидатор. Он должен возвращать Error объект,
    // если валидация проходит с ошибкой. Не используйте `console.warn` или throw,
    // так как это не работает внутри `oneOfType`.
    customProp: function(props, propName, componentName) {
      if (!/matchme/.test(props[propName])) {
        return new Error(
          'Invalid prop `' + propName + '` supplied to' +
          ' `' + componentName + '`. Validation failed.'
        );
      }
    },

    // Вы также можете определить пользовательский валидатор для `arrayOf` и `objectOf`.
    // Он должен возвращать Error объект, если валидация проходит с ошибкой.
    // Валидатор будет вызван для каждого ключа в массиве или объекте.
    // Первые два аргумента валидатора являются сам массив или объект, и текущий ключ элемента
    myCustomArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
      if (!/matchme/.test(propValue[key])) {
        return new Error(
          'Invalid prop `' + propFullName + '` supplied to' +
          ' `' + componentName + '`. Validation failed.'
        );
      }
    })
  };
  


3.2.2 Необходимость единственного потомка

Используя PropTypes.element вы можете указать, что только один потомок может быть передан в компонент как children.


Код
    
  import PropTypes from 'prop-types';

  class CustomComponent extends React.Component {
    render() {
      // Это должен быть в точности один элемент, иначе будет предупреждение
      const children = this.props.children;
      return (<div>{children}</div>);
    }
  }

  CustomComponent.propTypes = {
    children: PropTypes.element.isRequired
  };
  


3.3 Значения свойств по умолчанию

Вы можете определять значения по умолчанию для ваших свойств, используя специальное свойство defaultProps:


Код
    
  class HelloWorld extends React.Component {
    render() {
      return (<p>Привет, {this.props.name}!</p>);
    }
  }

  // Определяет значения свойств по умолчанию
  HelloWorld.defaultProps = {
    name: 'Вася'
  };

  // Отрисует "Привет, Вася!":
  ReactDOM.render(<HelloWorld />, document.getElementById('example'));
  

Если вы используете преобразование Babel, такое как transform-class-properties, вы также можете объявлять defaultProps как статическое свойство в классе React-компонента. Этот синтаксис еще не окончателен, и для его работы в браузере потребуется выполнить этап компиляции. Для получения дополнительной информации см. предложение для полей классов .


Код
    
  class HelloWorld extends React.Component {
    static defaultProps = {
      name: 'Вася'
    }

    render() {
      return (<p>Привет, {this.props.name}!</p>);
    }
  }
  

Свойство defaultProps будет использовано, чтобы гарантировать, что свойство this.props.name, будет иметь значение, если оно не было указано родительским компонентом. Проверка типов propTypes происходит после отработки defaultProps, поэтому проверка типов будет также применена и к defaultProps.