PropTypes
A library used for prop type validation:
import React from 'react';
import PropTypes from 'prop-types';
class OrderNumber extends React.Component {
render() {
return (
<span>Номер заказа: {this.props.orderId}</span>
);
}
}
OrderNumber.propTypes = {
orderId: PropTypes.number
};
function OrderNumber(props) {
return (
<span>Номер заказа: {props.orderId}</span>
);
}
OrderNumber.propTypes = {
orderId: PropTypes.number
};
Examples:
import PropTypes from 'prop-types';
ProductPage.propTypes = {
// Проверка пропса на соответствие определённому JS-типу.
optionalString: PropTypes.string,
optionalNumber: PropTypes.number,
optionalBool: PropTypes.bool,
optionalArray: PropTypes.array,
optionalObject: PropTypes.object,
optionalSymbol: PropTypes.symbol,
optionalFunc: PropTypes.func,
// Значение любого типа
optionalAny: PropTypes.any
// Всё, что может быть отрендерено:
// числа, строки, элементы или массивы
// (или фрагменты), содержащие эти типы
optionalNode: PropTypes.node,
// React-элемент
optionalElement: PropTypes.element,
// Тип React-элемента (например, MyComponent).
optionalElementType: PropTypes.elementType,
// Можно указать, что пропс должен быть экземпляром класса
// Для этого используется JS-оператор instanceof.
optionalMessage: PropTypes.instanceOf(Review),
// Вы можете задать ограничение конкретными значениями
// при помощи перечисления
optionalEnum: PropTypes.oneOf(['Size', 'Color', 'Brand']),
// Объект одного из нескольких типов
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(Review)
]),
// Массив объектов конкретного типа
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
// Объект со свойствами конкретного типа
optionalObjectOf: PropTypes.objectOf(PropTypes.number),
// Объект с определённой структурой
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
}),
// При наличии необъявленных свойств в объекте будут вызваны предупреждения
optionalObjectWithStrictShape: PropTypes.exact({
name: PropTypes.string,
quantity: PropTypes.number
}),
// Можно добавить `isRequired` к любому приведённому выше типу,
// чтобы показывать предупреждение,
// если пропс не передан
requiredFunc: PropTypes.func.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
вы можете указать, что в качестве дочернего может быть передан только один элемент:
import PropTypes from 'prop-types';
class ContainerBlock extends React.Component {
render() {
// Это должен быть ровно один элемент.
// Иначе вы увидите предупреждение
const children = this.props.children;
return (
<div>
{children}
</div>);
}
}
ContainerBlock.propTypes = {
children: PropTypes.element.isRequired
};
Chat example:
import React from 'react';
import PropTypes from 'prop-types';
import './styles.css';
const messagePropTypes = PropTypes.shape({
id: PropTypes.number.isRequired,
user: PropTypes.string.isRequired,
replyTo: PropTypes.number,
text: PropTypes.string.isRequired
});
const Message = ({ message, repliedMessage, className = 'message' }) => (
<div className={className}>
{repliedMessage && <RepliedMessage message={repliedMessage} />}
<h3>{message.user}</h3>
<p>{message.text}</p>
</div>
);
Message.propTypes = {
message: messagePropTypes.isRequired,
repliedMessage: messagePropTypes
};
const RepliedMessage = ({ message }) => <Message message={message} className={'replied-message'} />;
RepliedMessage.propTypes = {
message: messagePropTypes.isRequired
};
const Chat = ({ thread }) => (
<div className="tread">
{thread.map(message => {
const repliedMessage = thread.find(m => m.id === message.replyTo);
return <Message key={message.id} repliedMessage={repliedMessage} message={message} />;
})}
</div>
);
Chat.propTypes = {
thread: PropTypes.arrayOf(messagePropTypes).isRequired
};
export default class App extends React.Component {
state = {
thread: [
{
id: 1,
user: 'Тамара',
text: 'Всем привет! Кто в курсе, когда в нашем доме отключат горячую воду?'
},
{
id: 2,
user: 'Алексей',
replyTo: 1,
text: 'В подъезде висит объявление, скоро буду там, сфотографирую и пришлю сюда'
},
{
id: 3,
user: 'Катя',
replyTo: 2,
text: 'О! Спасибо! Ждём! :)'
}
]
};
render() {
return (
<div className="App">
<Chat thread={this.state.thread} />
</div>
);
}
}
#react