Prop-types
(скучный, но небольшой теоретический перекур)
Перед выполнением данного урока, не забывайте, что PropTypes не работает с production версией реакта. Эта фича только для разработки, так как валидация - дорогая операция.
Давайте сломаем наш код:
1
const App = () => {
2
return (
3
<React.Fragment>
4
<h3>Новости</h3>
5
<News/> {/* удалили передачу data */}
6
</React.Fragment>
7
)
8
}
Copied!
Обновим страницу - видим сообщение об ошибке.
no news error
В принципе, все понятно - мы пытаемся вызвать метод map у undefined. У примитива undefined, как известно никаких методов нет - ошибка, получите распишитесь. Хорошо, что кода мало и мы быстро выяснили в чем проблема. Еще лучше, что есть возможность улучшить наше положение, добавив propTypes - специальное свойство, которое будет "валидировать" наш компонент.
Добавьте загрузку еще одного скрипта в документ:
1
<script src="https://unpkg.com/[email protected]/prop-types.js"></script>
Copied!
Пусть вас не смущает версия 15.6 у пакета prop-types. Он с некоторых пор живет своей жизнью, отдельно от react.
Внесите изменения в компонент <News />
1
...
2
class News extends React.Component {
3
renderNews = () => {
4
...
5
}
6
render() {
7
...
8
}
9
}
10
11
// добавили propTypes.
12
// propTypes (с маленькой буквы) = свойство News
13
News.propTypes = {
14
data: PropTypes.array.isRequired // PropTypes (с большой буквы) = библиотека prop-types
15
}
16
...
Copied!
Обновите страницу:
Гораздо лучше! Исходя из текста ошибки нам сразу понятно куда копать: в render методе App, не указано свойство data, которое ожидается в News. Справедливости ради, ниже есть подобное сообщение, но ошибка там имеет универсальный текст.
Подробные "простыни" текста об ошибке - заслуга новых версий реакта. Это удобно.
Восстановим свойство data.
1
const App = () => {
2
return (
3
<React.Fragment>
4
<h3>Новости</h3>
5
<News data={myNews}/>
6
</React.Fragment>
7
)
8
}
Copied!
Вновь все работает, и наша консоль чиста.

Подробнее о propTypes

Приведу выдержку из офф.документации:
1
MyComponent.propTypes = {
2
propTypes: {
3
// Вы можете указать, каким примитивом должно быть свойство
4
optionalArray: PropTypes.array,
5
optionalBool: PropTypes.bool,
6
optionalFunc: PropTypes.func,
7
optionalNumber: PropTypes.number,
8
optionalObject: PropTypes.object,
9
optionalString: PropTypes.string,
10
optionalSymbol: PropTypes.symbol,
11
12
// ...
13
14
// Вы может указать, что свойство может быть одним из ...
15
optionalUnion: PropTypes.oneOfType([
16
PropTypes.string,
17
PropTypes.number,
18
PropTypes.instanceOf(Message)
19
])
20
21
// ...
22
23
// Вы можете указать, конкретную структуру объекта свойства
24
optionalObjectWithShape: PropTypes.shape({
25
color: PropTypes.string,
26
fontSize: PropTypes.number
27
}),
28
29
// Вы можете указать, что свойство ОБЯЗАТЕЛЬНО
30
requiredFunc: React.PropTypes.func.isRequired,
31
32
// Если нужно указать, что свойство просто обязательно, и может быть любым примитивом
33
requiredAny: React.PropTypes.any.isRequired,
34
35
// ... (в документации еще есть варианты)
36
}
37
};
Copied!
Согласно этому листингу, мы можем перевести правило, указанное в компоненте <News />:
PropTypes.array.isRequired - свойство должно быть массивом и оно обязательно должно быть!
Я вижу по глазам некоторых (да-да, вижу), что все это какая-то бесполезная лабуда. Итак понятно - есть ошибка, есть возможность тыкнуть на нее в дебаггере и посмотреть. Специально для вас, следующая ситуация: удалите из массива myNews автора, например в третьем элементе:
1
const myNews = [
2
{
3
id: 1,
4
author: 'Саша Печкин',
5
text: 'В четверг, четвертого числа...',
6
bigText: 'в четыре с четвертью часа четыре чёрненьких чумазеньких чертёнка чертили чёрными чернилами чертёж.'
7
},
8
{
9
id: 2,
10
author: 'Просто Вася',
11
text: 'Считаю, что $ должен стоить 35 рублей!',
12
bigText: 'А евро 42!'
13
},
14
{
15
id: 3,
16
// удалили автора
17
text: 'Прошло 2 года с прошлых учебников, а $ так и не стоит 35',
18
bigText: 'А евро опять выше 70.'
19
},
20
{
21
id: 4,
22
author: 'Гость',
23
text: 'Бесплатно. Без смс, про реакт, заходи - https://maxpfrontend.ru',
24
bigText: 'Еще есть группа VK, telegram и канал на youtube! Вся инфа на сайте, не реклама!'
25
}
26
];
Copied!
Посмотрим результат:
no author without prop-types
Никаких ошибок. Но наше приложение не работает так как надо. Кто виноват? Реакт? Backend-программист который прислал нам такие данные?
Программист, может и виноват. Но реакт точно нет. У нас получилось, что в this.props.data.author содержится undefined (переменнная не определена). Поэтому react так и поступил, и показал нам "ничего" (на скриншоте это только "двоеточие").
no author without prop-types more
Такую ошибку сложно отловить.
Добавьте propTypes в компонент <Article />
1
class Article extends React.Component {
2
render() {
3
...
4
}
5
}
6
7
Article.propTypes = {
8
data: PropTypes.shape({
9
author: PropTypes.string.isRequired,
10
text: PropTypes.string.isRequired
11
})
12
}
Copied!
В таком случае вы получите сообщение об ошибке:
no author with prop types error
Разве это не прекрасно?
Исходный код на данный момент.
P.S. Не забудьте вернуть автора ;)
Last modified 1yr ago