Использование props
У каждого компонента могут быть свойства. Они хранятся в this.props, и передаются компоненту как атрибуты.
Общий вид:
1
const wizard = {name: Garry, surname: Potter};
2
<MyComponent data={wizard} eshe_odno_svoistvo={[1,2,3,4,5]} />
Copied!
В свойство можно передать любой javascript примитив, объект, переменную и даже выражение. Значение свойства должно быть взято в фигурные скобки.
Значения доступны через this.props.ИМЯ_СВОЙСТВА (в statefull-компонентах) или в первом аргументе функции (в stateless).
В нашем случае, если говорить про statefull, мы получим:
  • this.props.data - объект {name: Garry, surname: Potter}
  • this.props.eshe_odno_svoistvo - массив [1,2,3,4,5]
this.props используются только для чтения!
Давайте создадим несколько новостей для нашего приложения.
Добавьте в начало script-тэга массив с данными
1
const myNews = [
2
{
3
author: 'Саша Печкин',
4
text: 'В четверг, четвертого числа...'
5
},
6
{
7
author: 'Просто Вася',
8
text: 'Считаю, что $ должен стоить 35 рублей!'
9
},
10
{
11
author: 'Max Frontend',
12
text: 'Прошло 2 года с прошлых учебников, а $ так и не стоит 35'
13
},
14
{
15
author: 'Гость',
16
text: 'Бесплатно. Без смс, про реакт, заходи - https://maxpfrontend.ru'
17
}
18
];
Copied!
И измените строку с подключением компонента News следующим образом:
index.html
1
...
2
const myNews = [
3
{
4
author: 'Саша Печкин',
5
text: 'В четверг, четвертого числа...'
6
},
7
{
8
author: 'Просто Вася',
9
text: 'Считаю, что $ должен стоить 35 рублей!'
10
},
11
{
12
author: 'Max Frontend',
13
text: 'Прошло 2 года с прошлых учебников, а $ так и не стоит 35'
14
},
15
{
16
author: 'Гость',
17
text: 'Бесплатно. Без смс, про реакт, заходи - https://maxpfrontend.ru'
18
}
19
];
20
21
const News = () => {
22
return <p>К сожалению, новостей нет</p>
23
}
24
25
const Comments = () => {
26
return <p>Нет новостей - комментировать нечего.</p>
27
}
28
29
const App = () => {
30
return (
31
<React.Fragment>
32
<News data={myNews}/> {/* добавили свойство data */}
33
<Comments />
34
</React.Fragment>
35
)
36
}
37
38
ReactDOM.render(
39
<App />,
40
document.getElementById('root')
41
);
42
...
Copied!
Обратите внимание, комментарии внутри JSX пишутся в фигурных скобках: {/* текст комментария */}
Так же прошу заметить, что JSX это не весь js-код, который содержится в тэге script, грубо говоря JSX - это HTML-разметка + переменные/выражения. Поэтому в остальных местах можно писать комментарии привычным для вас способом ( //... или /*...*/ )
Откройте в консоли вкладку react (конечно, предварительно обновив страницу).
свойства компонента News
Напомню: в данный момент, мы добавили свойство data в наш компонент <News />. Необязательно было называть свойство так, можно было написать, например:
1
<News posledine_novosti={my_news} />
Copied!
Тогда в консоли разработчика, это выглядело бы так:
last news
Ок, у нашего компонента есть свойство, в котором лежат наши новости, но компонент не умеет их отображать. Это легко исправить.
Представим HTML разметку для наших новостей:
1
<div class="news">
2
<p class="news__author">Саша Печкин:</p>
3
<p class="news__text">В четверг, четвертого числа...</p>
4
</div>
Copied!
Вопрос: У нас есть разметка для одного элемента данных, есть данные целиком (массив myNews). Как отобразить эти данные?
Ответ: Нужно создать шаблон, пройтись по всем переменным в массиве с новостями и подставить значения.
Когда вам нужно отобразить переменную в шаблоне разметки JSX - она так же оборачивается в фигурные скобки. На практике это выглядит проще, чем в теории, поэтому давайте представим, как может выглядеть наша JSX разметка:
1
this.props.data.map(function(item, index) {
2
return (
3
<div key={index}>
4
<p className="news__author">{item.author}:</p>
5
<p className="news__text">{item.text}</p>
6
</div>
7
)
8
})
Copied!
  1. 1.
    Мы использовали метод массивов - Map. Если вы незнакомы с ним, прочитайте документацию.
  2. 2.
    Мы обернули разметку внутри return в корневой элемент <div>. Мы могли бы обернуть ее в любой другой элемент, главное, напоминаю - внутри return всегда должен возвращаться DOM-узел (то есть, что угодно, обернутое в родительский тэг или в React.Fragment).
  3. 3.
    Мы использовали у родительского элемента атрибут key (<div key={index}>). Если объяснить предельно просто: реакту нужна уникальность, чтобы все его механизмы работали корректно. По "ключу" он будет понимать с каким именно дочерним узлом вы работаете и какому родителю он принадлежит. Индекс - не идеальный вариант для ключа, мы это исправим далее.
  4. 4.
    Мы использовали в шаблоне, значения переменных + текст, например <p className="news__author">{item.author}:</p> которое могло бы быть представлено в нативном js-коде как <p className="news__author">''+item.author+':'</p> (пустая строка + значение переменной + двоеточие)
В результате работы функции map, мы получили новый массив, состоящий из необходимых нам реакт-элементов. Это и есть решение нашей задачи, нам осталось лишь сохранить этот массив в переменной, например newsTemplate, и в render функции компонента <News /> вернуть разметку + "переменную-шаблон".
News по-быстрому переделаем в statefull (через class ... extends):
index.html
1
...
2
const myNews = [
3
{
4
author: 'Саша Печкин',
5
text: 'В четверг, четвертого числа...'
6
},
7
{
8
author: 'Просто Вася',
9
text: 'Считаю, что $ должен стоить 35 рублей!'
10
},
11
{
12
author: 'Max Frontend',
13
text: 'Прошло 2 года с прошлых учебников, а $ так и не стоит 35'
14
},
15
{
16
author: 'Гость',
17
text: 'Бесплатно. Без смс, про реакт, заходи - https://maxpfrontend.ru'
18
}
19
];
20
21
class News extends React.Component {
22
render() {
23
const newsTemplate = this.props.data.map(function(item, index) {
24
return (
25
<div key={index}>
26
<p className="news__author">{item.author}:</p>
27
<p className="news__text">{item.text}</p>
28
</div>
29
)
30
})
31
32
console.log(newsTemplate)
33
34
return (
35
<div className="news">
36
{newsTemplate}
37
</div>
38
)
39
}
40
}
41
...
Copied!
Посмотрим что получилось:
Вы еще не в восторге? Количество кода - кот наплакал.
Напоследок, мне не хочется, но придется вновь разрушить магию. Давайте посмотрим, что возвращает console.log(newsTemplate) (откройте вкладку Console).
Взглянем в консоль:
Объект, у объекта свойства... все как обычно в мире javascript.

Почему не стоит указывать index в качестве ключа

Если кому интересны причины, то приведу вам комментарий из старого учебника:
P.S. Здесь и в продолжении всего курса в коде для отображения массива новостей используется key = {index}. Обратите внимание на следующую ветку комментариев (спасибо DeLaVega и geakstr).
Суть в том, что index не лучший вариант для ключа, когда ваши "айтемы" могут менять порядок. У нас новости не меняются, но тем не менее, мы можем быстро решить нашу проблему добавив "действительно" уникальное значение, которое не будет изменяться, если у элементов поменяется index.
Конечно же, это свойство называется id ;) Добавим его в массив и будем использовать в качестве ключа.
index.html
1
...
2
const myNews = [
3
{
4
id: 1, // добавили id
5
author: 'Саша Печкин',
6
text: 'В четверг, четвертого числа...'
7
},
8
{
9
id: 2,
10
author: 'Просто Вася',
11
text: 'Считаю, что $ должен стоить 35 рублей!'
12
},
13
{
14
id: 3,
15
author: 'Max Frontend',
16
text: 'Прошло 2 года с прошлых учебников, а $ так и не стоит 35'
17
},
18
{
19
id: 4,
20
author: 'Гость',
21
text: 'Бесплатно. Без смс, про реакт, заходи - https://maxpfrontend.ru'
22
}
23
];
24
25
class News extends React.Component {
26
render() {
27
const newsTemplate = this.props.data.map(function(item) {
28
return (
29
<div key={item.id}> {/* используем id в качестве ключа */}
30
<p className="news__author">{item.author}:</p>
31
<p className="news__text">{item.text}</p>
32
</div>
33
)
34
})
35
36
return (
37
<div className="news">
38
{newsTemplate}
39
</div>
40
)
41
}
42
}
43
...
Copied!
Итого: мы научились отображать свойства компонента.
Исходный код на текущий момент. Не забудьте удалить console.log.
Last modified 1yr ago