# Использование props

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

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

## Использование props

У каждого компонента могут быть свойства. Они хранятся в `this.props`, и передаются компоненту как атрибуты.

**Общий вид:**

```javascript
var value1 = {name: Garry, surname: Potter};
<MyComponent data={value1} eshe_odno_svoistvo={[1,2,3,4,5]} />
```

В свойство можно передать любой javascript примитив, объект, переменную и даже выражение. Значение свойства должно быть взято в фигурные скобки.

Значения доступны через `this.props.ИМЯ_СВОЙСТВА`

В нашем случае, мы получим:

* *this.props.data* - объект `{name: Garry, surname: Potter}`
* *this.props.eshe\_odno\_svoistvo* - массив `[1,2,3,4,5]`

this.props используются **только** для чтения!

Давайте создадим несколько новостей для нашего приложения.

Добавьте в начало файла js/app.js

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

И измените строку с подключением компонента News следующим образом:

```javascript
var App = React.createClass({
  render: function() {
    return (
      <div className="app">
        Всем привет, я компонент App! Я умею отображать новости.
        <News data={my_news} /> {/*добавили свойство data */}
        <Comments />
      </div>
    );
  }
});
```

Обратите внимание, комментарии внутри JSX пишутся в фигурных скобках: `{/* текст комментария */}`

Так же прошу заметить, JSX это не весь js-код, который содержится в *App.js*, грубо говоря JSX - это HTML-разметка + переменные/выражения. Поэтому в остальных местах можно писать комментарии привычным для вас способом ( //... или /\*...\*/ )

Откройте в консоли вкладку react (конечно, предварительно обновив страницу).

![свойства компонента News](/files/-LvLn65Bviwuv16PAI50)

**Напомню**: в данный момент, мы добавили свойство *data* в наш компонент `<News />`. Необязательно было называть свойство так, можно было написать, например:

```javascript
<News posledine_novosti={my_news} />
```

Тогда в консоли разработчика, это выглядело бы так: ![last news](/files/-LvLn65D0nVl4T1ND_ux)

Сейчас у нашего компонента есть свойство, в котором лежат наши новости, но компонент не умеет их отображать. Это легко исправить.

Представим HTML разметку для наших новостей:

```markup
<div class="news">
  <p class="news__author">Саша Печкин:</p>
  <p class="news__text">В четверг, четвертого числа...</p>
</div>
```

**Вопрос:** У нас есть разметка для одного элемента данных, есть данные целиком (массив my\_news). Как отобразить эти данные?

**Ответ:** Нужно создать шаблон, пройтись по всем переменным в массиве с новостями и подставить значения.

Когда вам нужно отобразить переменную в шаблоне разметки - она так же оборачивается в фигурные скобки. На практике это выглядит проще, чем в теории, поэтому давайте представим, как может выглядеть наша JSX разметка:

```javascript
this.props.data.map(function(item, index) {
  return (
    <div key={index}>
      <p className="news__author">{item.author}:</p>
      <p className="news__text">{item.text}</p>
    </div>
  )
})
```

1. Мы использовали метод массивов - *Map*. Если вы незнакомы с ним, [прочитайте документацию](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/map).
2. Мы обернули разметку внутри *return* в корневой элемент `<div>`. Мы могли бы обернуть ее в любой другой элемент, главное, что нужно **запомнить** - внутри *return* всегда должен возвращаться DOM-узел (то есть, что угодно, обернутое в родительский тэг).
3. Мы использовали у родительского элемента атрибут **key** (`<div key={index}>`). Если объяснить предельно просто: реакту нужна уникальность, чтобы все его механизмы работали корректно. По "ключу" *он* будет понимать с каким именно дочерним узлом вы работаете и какому родителю он принадлежит. По поводу использования индекса в качестве ключа в конце урока есть ценное замечание.
4. Мы использовали в шаблоне, значения переменных + текст, например `<p className="news__author">{item.author}:</p>` могло бы быть представлено в нативном js-коде как `<p className="news__author">''+item.author+':'</p>` (пустая строка + значение переменной + двоеточие)

В результате работы функции map, мы получили новый массив, состоящий из необходимых нам реакт-элементов. Это и есть решение нашей задачи, нам осталось лишь сохранить этот массив в переменной, например `newsTemplate`, и в *render* функции компонента `<News />` вернуть разметку + "переменную-шаблон".

*js/app.js*

```javascript
...
var News = React.createClass({
  render: function() {
    var data = this.props.data;
    var newsTemplate = data.map(function(item, index) {
      return (
        <div key={index}>
          <p className="news__author">{item.author}:</p>
          <p className="news__text">{item.text}</p>
        </div>
      )
    })

    return (
      <div className="news">
        {newsTemplate}
      </div>
    );
  }
});
...
```

Посмотрим что получилось: ![news screenshot](/files/-LvLn65IFKgtYt5gGt4e)

Напоследок, мне не хочется, но придется вновь разрушить магию. Давайте сконсолим, *newsTemplate*. Просто добавьте console.log перед return'ом метода *render* компонента `<News />`.

*js/app.js*

```javascript
...
var News = React.createClass({
  render: function() {
    var data = this.props.data;
    var newsTemplate = data.map(function(item, index) {
      return (
        <div key={index}>
          <p className="news__author">{item.author}:</p>
          <p className="news__text">{item.text}</p>
        </div>
      )
    })

    console.log(newsTemplate);

    return (
      <div className="news">
        {newsTemplate}
      </div>
    );
  }
});
...
```

Взглянем в консоль: ![no magic news screen](/files/-LvLn65O5LW1HiuIeO_v)

Объект, у объекта свойства... все как обычно в мире javascript.

**Итого**: мы научились отображать свойства компонента.

[Исходный код](https://github.com/maxfarseer/react-ru-tutorial/tree/work_with_props) на текущий момент здесь. Не забудьте удалить console.log.

P.S. Здесь и в продолжении всего курса в коде для отображения массива новостей используется `key = {index}`. Обратите внимание на следующую ветку [комментариев](https://habrahabr.ru/post/279249/#comment_8807873) (спасибо *DeLaVega* и *geakstr*).


---

# 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:

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

The question should be specific, self-contained, and written in natural language.
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.
