(скучный, но небольшой теоретический перекур)
Перед выполнением данного урока, не забывайте, что PropTypes не работает с production версией реакта. Эта фича только для разработки, так как валидация - дорогая операция.
Давайте сломаем наш код:
const App = () => {return (<React.Fragment><h3>Новости</h3><News/> {/* удалили передачу data */}</React.Fragment>)}
Обновим страницу - видим сообщение об ошибке.
В принципе, все понятно - мы пытаемся вызвать метод 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 (с маленькой буквы) = свойство NewsNews.propTypes = {data: PropTypes.array.isRequired // PropTypes (с большой буквы) = библиотека prop-types}...
Обновите страницу:
Гораздо лучше! Исходя из текста ошибки нам сразу понятно куда копать: в render методе App, не указано свойство data, которое ожидается в News. Справедливости ради, ниже есть подобное сообщение, но ошибка там имеет универсальный текст.
Подробные "простыни" текста об ошибке - заслуга новых версий реакта. Это удобно.
Восстановим свойство data.
const App = () => {return (<React.Fragment><h3>Новости</h3><News data={myNews}/></React.Fragment>)}
Вновь все работает, и наша консоль чиста.
Приведу выдержку из офф.документации:
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! Вся инфа на сайте, не реклама!'}];
Посмотрим результат:
Никаких ошибок. Но наше приложение не работает так как надо. Кто виноват? Реакт? Backend-программист который прислал нам такие данные?
Программист, может и виноват. Но реакт точно нет. У нас получилось, что в this.props.data.author
содержится undefined
(переменнная не определена). Поэтому react так и поступил, и показал нам "ничего" (на скриншоте это только "двоеточие").
Такую ошибку сложно отловить.
Добавьте propTypes в компонент <Article />
class Article extends React.Component {render() {...}}Article.propTypes = {data: PropTypes.shape({author: PropTypes.string.isRequired,text: PropTypes.string.isRequired})}
В таком случае вы получите сообщение об ошибке:
Разве это не прекрасно?
Исходный код на данный момент.
P.S. Не забудьте вернуть автора ;)