Перейти к содержанию

Проверка типов с помощью PropTypes

Примечание:

С версии React 15.5 React.PropTypes были вынесены в отдельный пакет. Так что используйте библиотеку prop-types.

Вы можете использовать codemod-скрипт, чтобы провести замену в коде на использование этой библиотеки.

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import PropTypes from 'prop-types'

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

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

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

PropTypes

Пример использования возможных валидаторов:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import PropTypes from 'prop-types'

MyComponent.propTypes = {
  // Можно объявить проп на соответствие определённому JS-типу.
  // По умолчанию это не обязательно.
  optionalArray: PropTypes.array,
  optionalBool: PropTypes.bool,
  optionalFunc: PropTypes.func,
  optionalNumber: PropTypes.number,
  optionalObject: PropTypes.object,
  optionalString: PropTypes.string,
  optionalSymbol: PropTypes.symbol,

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

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

  // Можно указать, что проп должен быть экземпляром класса
  // Для этого используется оператор `instanceof`.
  optionalMessage: PropTypes.instanceOf(Message),

  // Вы можете задать ограничение конкретными значениями
  // при помощи перечисления
  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,
  }),

  // Можно добавить`isRequired` к любому из приведённому выше типу,
  // чтобы показывать предупреждение,
  // если проп не передан
  requiredFunc: PropTypes.func.isRequired,

  // Значение любого типа
  requiredAny: PropTypes.any.isRequired,

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

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

Ограничение на один дочерний компонент

С помощью PropTypes.element вы можете указать, что в качестве дочернего может быть передан только один элемент.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import PropTypes from 'prop-types'

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

MyComponent.propTypes = {
  children: PropTypes.element.isRequired,
}

Значения пропсов по умолчанию

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Greeting extends React.Component {
  render() {
    return <h1>Привет, {this.props.name}</h1>
  }
}

// Задание значений по умолчанию для пропсов:
Greeting.defaultProps = {
  name: 'Незнакомец',
}

// Отрендерит "Привет, Незнакомец":
ReactDOM.render(
  <Greeting />,
  document.getElementById('example')
)

Если вы используете один из Babel-плагинов по преобразованию кода, вроде transform-class-properties, то можете объявить defaultProps как статическое свойство класса (для компонента-наследника от React.Component). Этот синтаксис ещё не утверждён, так что для его работы в браузере нужна компиляция. Подробнее смотрите в предложении о полях класса.

1
2
3
4
5
6
7
8
9
class Greeting extends React.Component {
  static defaultProps = {
    name: 'незнакомец',
  }

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

Определение defaultProps гарантирует, что this.props.name будет иметь значение, даже если оно не было указано родительским компонентом. Сначала применяются значения по умолчанию, заданные в defaultProps. После запускается проверка типов с помощью propTypes. Так что проверка типов распространяется и на значения по умолчанию.

Комментарии