Теги в массивах и циклах JSX


Пусть у нас в массиве хранятся теги:

function App() {
const arr = [<p>1</p>, <p>2</p>, <p>3</p>];
}
Мы можем выполнить вставку содержимого нашей переменной с помощью фигурных скобок:

function App() {
const arr = [<p>1</p>, <p>2</p>, <p>3</p>];

return <div>
{arr}
</div>;
}
В результате теги из массива вставятся в указанное место и после рендеринга получится следующий код:

<div>
<p>1</p>
<p>2</p>
<p>3</p>
</div>

Формирование в цикле
Массив с тегами можно создать в цикле:

function App() {
const arr = [];

for (let i = 0; i <= 9; i++) {
arr.push(<p>{i}</p>);
}

return <div>
{arr}
</div>;
}

Формирование из массива с данными
Пусть у нас есть какой-нибудь массив с некими данными, например, вот такой:

function App() {
const arr = [1, 2, 3, 4, 5];
}
Давайте положим каждый элемент этого массива в абзац и выведем эти абзацы в диве. Для этого мы можем воспользоваться любым удобным циклом JavaScript. Например, обычным for-of:

function App() {
const arr = [1, 2, 3, 4, 5];
const res = [];

for (const elem of arr) {
res.push(<p>{elem}</p>);
}

return <div>
{res}
</div>;
}
Однако, в React для таких дел более принято использовать цикл map:

function App() {
const arr = [1, 2, 3, 4, 5];

const res = arr.map(function(item) {
return <p>{item}</p>;
});

return <div>
{res}
</div>;
}

Проблема с ключами
В предыдущем примере мы формировали наши абзацы в цикле, вот так:

const res = arr.map(function(item, index) {
return <p>{item}</p>;
});
Это будет работать, однако, если заглянуть в консоль - мы увидим ошибку: Warning: Each child in an array or iterator should have a unique "key" prop. В данном случае React требует, чтобы каждому тегу из цикла мы дали уникальный номер, чтобы React было проще с этими тегами работать в дальнейшем.

Этот номер добавляется с помощью атрибута key. В данном случае в качестве номера мы можем взять номер элемента в массиве. В нашем случае этот номер хранится в переменной index и значит исправленная строка будет выглядеть вот так:

const res = arr.map(function(item, index) {
return <p key={index}>{item}</p>;
});
Давайте запустим - ошибка из консоли исчезнет:

function App() {
const arr = [1, 2, 3, 4, 5];

const res = arr.map(function(item, index) {
return <p key={index}>{item}</p>;
});

return <div>
{res}
</div>;
}
Еще раз: этот атрибут key имеет служебное значение для React, более глубоко вы поймете этот момент в следующих уроках. Пока просто знайте: если вы видите такую ошибку - добавьте атрибут key с уникальным для каждого тега значением и проблема исчезнет.

Ключ key должен быть уникальным только внутри этого цикла, в другом цикле значения key могут совпадать со значениями из другого цикла.