Книга: react-course-ru-v2
Назад: Порефакторим...
Дальше: Использование state

Prop-types

Prop-types

(скучный, но небольшой теоретический перекур)

Перед выполнением данного урока, не забывайте, что PropTypes не работает с production версией реакта. Эта фича только для разработки, так как валидация - дорогая операция.


Давайте сломаем наш код:

const App = () => {   return (     <React.Fragment>       <h3>Новости</h3>       <News/> {/* удалили передачу data */}     </React.Fragment>   ) } 

Обновим страницу - видим сообщение об ошибке.

no news error

В принципе, все понятно - мы пытаемся вызвать метод map у undefined. У примитива undefined, как известно никаких методов нет - ошибка, получите распишитесь. Хорошо, что кода мало и мы быстро выяснили в чем проблема. Еще лучше, что есть возможность улучшить наше положение, добавив propTypes - специальное свойство, которое будет "валидировать" наш компонент.

Добавьте загрузку еще одного скрипта в документ:

<script src="https://unpkg.com/[email protected]/prop-types.js"></script> 

Пусть вас не смущает версия 15.6 у пакета prop-types. Он с некоторых пор живет своей жизнью, отдельно от react.

Внесите изменения в компонент <News />

... class News extends React.Component {   renderNews = () => {     ...   }   render() {     ...   } }  // добавили propTypes.  // propTypes (с маленькой буквы) = свойство News News.propTypes = {   data: PropTypes.array.isRequired // PropTypes (с большой буквы) = библиотека prop-types } ... 

Обновите страницу: data is required error

Гораздо лучше! Исходя из текста ошибки нам сразу понятно куда копать: в render методе App, не указано свойство data, которое ожидается в News. Справедливости ради, ниже есть подобное сообщение, но ошибка там имеет универсальный текст.

Подробные "простыни" текста об ошибке - заслуга новых версий реакта. Это удобно.

Восстановим свойство data.

const App = () => {   return (     <React.Fragment>       <h3>Новости</h3>       <News data={myNews}/>     </React.Fragment>   ) } 

Вновь все работает, и наша консоль чиста.


Подробнее о propTypes

Приведу выдержку из :

MyComponent.propTypes = {   propTypes: {     // Вы можете указать, каким примитивом должно быть свойство     optionalArray: PropTypes.array,     optionalBool: PropTypes.bool,     optionalFunc: PropTypes.func,     optionalNumber: PropTypes.number,     optionalObject: PropTypes.object,     optionalString: PropTypes.string,     optionalSymbol: PropTypes.symbol,      // ...      // Вы может указать, что свойство может быть одним из ...     optionalUnion: PropTypes.oneOfType([       PropTypes.string,       PropTypes.number,       PropTypes.instanceOf(Message)     ])      // ...      // Вы можете указать, конкретную структуру объекта свойства     optionalObjectWithShape: PropTypes.shape({       color: PropTypes.string,       fontSize: PropTypes.number     }),      // Вы можете указать, что свойство ОБЯЗАТЕЛЬНО     requiredFunc: React.PropTypes.func.isRequired,      // Если нужно указать, что свойство просто обязательно, и может быть любым примитивом     requiredAny: React.PropTypes.any.isRequired,      // ... (в документации еще есть варианты)   } }; 

Согласно этому листингу, мы можем перевести правило, указанное в компоненте <News />:

PropTypes.array.isRequired - свойство должно быть массивом и оно обязательно должно быть!


Я вижу по глазам некоторых (да-да, вижу), что все это какая-то бесполезная лабуда. Итак понятно - есть ошибка, есть возможность тыкнуть на нее в дебаггере и посмотреть. Специально для вас, следующая ситуация: удалите из массива myNews автора, например в третьем элементе:

const myNews = [   {     id: 1,     author: 'Саша Печкин',     text: 'В четверг, четвертого числа...',     bigText: 'в четыре с четвертью часа четыре чёрненьких чумазеньких чертёнка чертили чёрными чернилами чертёж.'   },   {     id: 2,     author: 'Просто Вася',     text: 'Считаю, что $ должен стоить 35 рублей!',     bigText: 'А евро 42!'   },   {     id: 3,     // удалили автора     text: 'Прошло 2 года с прошлых учебников, а $ так и не стоит 35',     bigText: 'А евро опять выше 70.'   },   {     id: 4,     author: 'Гость',     text: 'Бесплатно. Без смс, про реакт, заходи - https://maxpfrontend.ru',     bigText: 'Еще есть группа VK, telegram и канал на youtube! Вся инфа на сайте, не реклама!'   } ]; 

Посмотрим результат:

no author without prop-types

Никаких ошибок. Но наше приложение не работает так как надо. Кто виноват? Реакт? Backend-программист который прислал нам такие данные?

Программист, может и виноват. Но реакт точно нет. У нас получилось, что в this.props.data.author содержится undefined (переменнная не определена). Поэтому react так и поступил, и показал нам "ничего" (на скриншоте это только "двоеточие").

no author without prop-types more

Такую ошибку сложно отловить.

Добавьте propTypes в компонент <Article />

class Article extends React.Component {   render() {     ...   } }  Article.propTypes = {   data: PropTypes.shape({     author: PropTypes.string.isRequired,     text: PropTypes.string.isRequired   }) } 

В таком случае вы получите сообщение об ошибке:

no author with prop types error

Разве это не прекрасно?

на данный момент.

P.S. Не забудьте вернуть автора ;)

Назад: Порефакторим...
Дальше: Использование state