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

ОБНОВЛЕНИЕ 2018: в учебнике хорошая теория, но ему уже два года. Проверяйте версии пакетов. За выходом нового учебника можно следить в telegram канале или twitter

На канале так же проводятся бесплатные вебинары, публикуются переводы и авторские материалы, присоединяйтесь!

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

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

Общий вид:

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

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

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

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 (конечно, предварительно обновив страницу).

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

<News posledine_novosti={my_news} />

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

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

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

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

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

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

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. Если вы незнакомы с ним, прочитайте документацию.

  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

...
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>
    );
  }
});
...

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

js/app.js

...
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>
    );
  }
});
...

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

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

Исходный код на текущий момент здесь. Не забудьте удалить console.log.

P.S. Здесь и в продолжении всего курса в коде для отображения массива новостей используется key = {index}. Обратите внимание на следующую ветку комментариев (спасибо DeLaVega и geakstr).

Last updated