Валидация свойств React компонентов

Когда приложение становится большим и содержит множество компонентов, важно быть уверенным в том, что эти компоненты используются правильно. Сделать это можно с помощью определения propTypes. React.PropTypes предоставляет доступ к набору валидаторов, которые используются для того, чтобы убедиться в том, что компонентам передаются правильные данные. О данных, не прошедших валидацию, React сообщит нам в виде сообщения warning в консоли JavaScript. Стоит отметить, что по причине производительности эти сообщения будут отображаться только в режиме разработчика.

Самые простые — это валидаторы базовых типов JavaScript. Вот они:

someArrayProp: React.PropTypes.array
someBoolProp: React.PropTypes.bool
someFunction: React.PropTypes.func
someNumberProp: React.PropTypes.number
someObject: React.PropTypes.object
someString: React.PropTypes.string

В случае, если нужно убедиться, что значение свойства будет отображено в браузере (будь то это строка, число, React-элемент или массив, состоящих из элементов этих типов), то необходимо использовать:

someNode: React.PropTypes.node

Для React-элемента:

someElement: React.PropTypes.element

Для того, чтобы проверить, является ли свойство экземпляром определенного класса (в этом случае используется JavaScript instanceOf оператор):

instanceOfSomeClass: React.PropTypes.instanceOf(SomeClass)

Если свойство может принимать ограниченный набор значений:

someProp: React.PropTypes.oneOf(['One', 'Two', ...])

Значения, передаваемые в виде массива в метод oneOf необязательно должны иметь один и тот же тип данных. Например, конструкция вида

someProp: React.PropTypes.oneOf(['One', 2, true, ...])

также будет корректно работать.

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

someProp: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
React.PropTypes.instanceOf(SomeClass)
])

Если свойство — это массив значений определенного типа:

someArray: React.PropTypes.arrayOf(React.PropTypes.number)

В случае, если свойство — это объект с набором свойств определенного типа:

someObj: React.PropTypes.objectOf(React.PropTypes.number)

Если объект должен иметь свойства определенных типов:

someObj: React.PropTypes.shape({
color: React.PropTypes.string,
fontSize: React.PropTypes.number
})

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

someProp: React.PropTypes.string.isRequired
someArr: React.PropTypes.arrayOf(React.PropTypes.string).isRequired

Если требуется просто указать на обязательность заполнения свойства:

someProp: React.PropTypes.any.isRequired

Стоит отметить, что нельзя использовать React.PropTypes.isRequired для указания обязательного заполнения свойства. В этом случае в консоли будет отображено следующее:

Warning: Failed propType: React class: prop type `someProp` is invalid; it must be a function, usually from React.PropTypes.

React позволяет писать свои собственные функции-валидаторы. При этом функция должна возвращать Error объект, если валидация завершилась неудачей. Не стоит здесь использовать console.warn или throw.

customProp: function(props, propName, componentName) { 
if (!customTestFunc(props[propName])) {
return new Error( 'Ошибка для свойства ' + propName );
}
}
customTestFunc(value) {
// код для валидации значения свойства
// return true or false
}

Также можно написать собственный валидатор для arrayOf и objectOf. Валидатор будет вызван для каждого элемента массива или свойства объекта.

// propValue - это массив или объект
// key - текущий ключ для доступа к элементу массива или свойству объекта
customArrayProp: React.PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) { 
if (!customTestFunc(propValue[key])) {
return new Error( 'Ошибка для свойства ' + propName );
}
})

Один потомок

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

class MyComponent extends React.Component {
static propTypes = {
children: React.PropTypes.element.isRequired
}
    render() {
return (
<div>
{this.props.children}
</div>
);
}
}
class TestComponent extends React.Component {
render() {
return (
<div>
{// один потомок - ошибок нет}
<MyComponent>
<div><span>some</span><span>text</span></div>
</MyComponent>
                {// в консоли будет сообщение об ошибке}            
<MyComponent>
<div>some node</div>
<div>another node - warning</div>
</MyComponent>
</div>
);
}
}

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

React позволяет установить значения для свойств, которые будут использоваться по умолчанию:

class MyComponent extends React.Component {...}
MyComponent.defaultProps = { 
someProp: 0,
anotherProp: 'test',
...
}

Ссылки

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.