> For the complete documentation index, see [llms.txt](https://max-frontend.gitbook.io/react-course-ru/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://max-frontend.gitbook.io/react-course-ru/reactproptypes.md).

# React.propTypes

*ОБНОВЛЕНИЕ 2018: в учебнике хорошая теория, но ему уже два года. Проверяйте версии пакетов. За выходом нового учебника можно следить в* [*telegram канале*](http://bit.ly/2tS7QUC) *или* [*twitter*](http://bit.ly/2HADDLE)

*На* [*канале*](http://bit.ly/2tS7QUC) *так же проводятся бесплатные вебинары, публикуются переводы и авторские материалы,* [*присоединяйтесь*](http://bit.ly/2tS7QUC)*!*

## React.propTypes

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

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

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

```javascript
var App = React.createClass({
  render: function() {
    return (
      <div className='app'>
        <h3>Новости</h3>
        <News /> {/* удалили data = {my_news} */}
      </div>
    );
  }
});
```

Обновим страницу - видим сообщение об ошибке. ![no news error](/files/-LvLnHHZ4qdiXw19za18)

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

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

```javascript
var News = React.createClass({
  propTypes: {
    data: React.PropTypes.array.isRequired
  },
  render: function() {
    var data = this.props.data;
    var newsTemplate;

    if (data.length > 0) {
      newsTemplate = data.map(function(item, index) {
        return (
          <div key={index}>
            <Article data={item} />
          </div>
        )
      })
    } else {
      newsTemplate = <p>К сожалению новостей нет</p>
    }

    return (
      <div className='news'>
        {newsTemplate}
        <strong className={'news__count ' + (data.length > 0 ? '':'none') }>Всего новостей: {data.length}</strong>
      </div>
    );
  }
});
```

Обновите страницу: ![no news error with propTypes](/files/-LvLnHHbgi-kw9vHc_Ro)

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

```javascript
var App = React.createClass({
  render: function() {
    return (
      <div className='app'>
        <h3>Новости</h3>
        <News data={my_news}/>
      </div>
    );
  }
});
```

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

### Подробнее о propTypes

Приведу выдержку из [офф.документации](https://facebook.github.io/react/docs/reusable-components.html):

```javascript
React.createClass({
  propTypes: {
    // Вы можете указать, каким примитивом должно быть свойство
    optionalArray: React.PropTypes.array,
    optionalBool: React.PropTypes.bool,
    optionalFunc: React.PropTypes.func,
    optionalNumber: React.PropTypes.number,
    optionalObject: React.PropTypes.object,
    optionalString: React.PropTypes.string,

    // Вы может указать, что свойство можеть быть одни из ...
    optionalUnion: React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.number,
      React.PropTypes.instanceOf(Message)
    ]),

    // Вы можете указать, конкретную структуру объекта свойства
    optionalObjectWithShape: React.PropTypes.shape({
      color: React.PropTypes.string,
      fontSize: React.PropTypes.number
    }),

    // Вы можете указать, что свойство ОБЯЗАТЕЛЬНО
    requiredFunc: React.PropTypes.func.isRequired,

    // Если нужно указать, что свойство просто обязательно, и может быть любым примитивом
    requiredAny: React.PropTypes.any.isRequired,

  }
});
```

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

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

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

```javascript
var my_news = [
  {
    author: 'Саша Печкин',
    text: 'В четчерг, четвертого числа...'
  },
  {
    author: 'Просто Вася',
    text: 'Считаю, что $ должен стоить 35 рублей!'
  },
  {
    text: 'Бесплатно. Скачать. Лучший сайт - http://localhost:3000'
  }
];
```

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

![no author](/files/-LvLnHHdseuk7jhsnU9r)

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

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

![no author 2](/files/-LvLnHHfSTWGvgMxmscZ)

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

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

```javascript
var Article = React.createClass({
  propTypes: {
    data: React.PropTypes.shape({
      author: React.PropTypes.string.isRequired,
      text: React.PropTypes.string.isRequired
    })
  },
  render: function() {
    var author = this.props.data.author,
        text = this.props.data.text;

    return (
      <div className='article'>
        <p className='news__author'>{author}:</p>
        <p className='news__text'>{text}</p>
      </div>
    )
  }
});
```

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

![no author error](/files/-LvLnHHh1_EOo0gYujDU)

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

[Исходный код](https://github.com/maxfarseer/react-ru-tutorial/tree/add_PropTypes) на данный момент.

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


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://max-frontend.gitbook.io/react-course-ru/reactproptypes.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
