Рэндэрынг спісаў
Часта ўзнікае неабходнасць адлюстравання шэрагу падобных кампанентаў на аснове набору даных. Каб маніпуліраваць масівам даных можна выкарыстоўваць метады масіваў JavaScript. На гэтай старонцы вы будзеце выкарыстоўваць метады filter()
і map()
разам з React для фільтрацыі і пераўтварэння масіву даных у масіў кампанентаў.
You will learn
- Як рэндэрыць кампаненты з масіву з дапамогай метаду
map()
- Як рэндэрыць толькі пэўныя кампаненты з дапамогай метаду
filter()
- Калі і навошта выкарыстоўваць ключы ў React
Рэндэрынг даных з масіваў
Дапусцім, у вас ёсць спіс кантэнту.
<ul>
<li>Крэола Кэтрын Джонсан: матэматык</li>
<li>Марыа Хасэ Маліна-Паскель Энрыкес: хімік</li>
<li>Махамад Абдус Салам: фізік</li>
<li>Персі Лавон Джуліан: хімік</li>
<li>Субрахманьян Чандрасекар: астрафізік</li>
</ul>
Адзіная розніца паміж гэтымі пунктамі спісу — іх змест, іх даныя. Пры стварэнні інтэрфейсаў часта трэба паказваць некалькі асобнікаў аднаго і таго ж кампанента, выкарыстоўваючы розныя даныя: ад спісаў каментарыяў да галерэй відарысаў профілю. У такіх сітуацыях вы можаце захоўваць гэтыя даныя ў аб’ектах і масівах JavaScript і выкарыстоўваць такія метады, як map()
і filter()
, каб рэндэрыць з іх спісы кампанентаў.
Вось кароткі прыклад таго, як стварыць спіс элементаў з масіву:
- Перамясціце даныя ў масіў:
const people = [
'Крэола Кэтрын Джонсан: матэматык',
'Марыа Хасэ Маліна-Паскель Энрыкес: хімік',
'Махамад Абдус Салам: фізік',
'Персі Лавон Джуліан: хімік',
'Субрахманьян Чандрасекар: астрафізік'
];
- Пераўтварыце элементы масіву
people
у новы масіў JSX вузлоў —listItems
:
const listItems = people.map(person => <li>{person}</li>);
- Вярніце
listItems
з вашага кампанента, абгарнуўшы іх у<ul>
:
return <ul>{listItems}</ul>;
Вось што мусіць атрымацца ў выніку:
const people = [ 'Крэола Кэтрын Джонсан: матэматык', 'Марыа Хасэ Маліна-Паскель Энрыкес: хімік', 'Махамад Абдус Салам: фізік', 'Персі Лавон Джуліан: хімік', 'Субрахманьян Чандрасекар: астрафізік' ]; export default function List() { const listItems = people.map(person => <li>{person}</li> ); return <ul>{listItems}</ul>; }
Звярніце ўвагу, што ў кансолі пясочніцы адлюстроўваецца памылка:
Вы даведаецеся, як выправіць гэтую памылку пазней на гэтай старонцы. Перш чым перайсці да гэтага, давайце дададзім некаторую структуру да даных.
Фільтрацыя масіваў элементаў
Структуру гэтых даных можна палепшыць.
const people = [{
id: 0,
name: 'Крэола Кэтрын Джонсан',
profession: 'матэматык',
}, {
id: 1,
name: 'Марыа Хасэ Маліна-Паскель Энрыкес',
profession: 'хімік',
}, {
id: 2,
name: 'Махамад Абдус Салам',
profession: 'фізік',
}, {
id: 3,
name: 'Персі Лавон Джуліан',
profession: 'хімік',
}, {
id: 4,
name: 'Субрахманьян Чандрасекар',
profession: 'астрафізік',
}];
Дапусцім, вы хочаце паказаць толькі людзей, чыя прафесія 'хімік'
. Каб вярнуць толькі гэтых людзей, вы можаце выкарыстоўваць JavaScript метад filter()
. Гэты метад бярэ масіў элементаў, прапускае іх праз «тэст» (функцыю, якая вяртае true
або false
) і вяртае новы масіў толькі з тых элементаў, якія прайшлі праверку (вярнулі true
).
Нам патрэбны толькі элементы, дзе profession
з’яўляецца 'хімік'
. Функцыя “тэст” для гэтага выглядае так: (person) => person.profession === 'хімік'
. Вось як сабраць гэта ўсё разам:
- Стварыце новы масіў толькі з «хімікаў» (пераменная
chemists
) выклікаўшы метадfilter()
наpeople
для фільтрацыі паperson.profession === 'хімік'
:
const chemists = people.filter(person =>
person.profession === 'хімік'
);
- Цяпер пераўтварыце элементы масіву
chemists
:
const listItems = chemists.map(person =>
<li>
<img
src={getImageUrl(person)}
alt={person.name}
/>
<p>
<b>{person.name}:</b>
{' ' + person.profession}.
Галоўнае дасягненне: {person.accomplishment}
</p>
</li>
);
- Нарэшце, вярніце
listItems
з вашага кампанента:
return <ul>{listItems}</ul>;
import { people } from './data.js'; import { getImageUrl } from './utils.js'; export default function List() { const chemists = people.filter(person => person.profession === 'хімік' ); const listItems = chemists.map(person => <li> <img src={getImageUrl(person)} alt={person.name} /> <p> <b>{person.name}:</b> {' ' + person.profession}. Галоўнае дасягненне: {person.accomplishment} </p> </li> ); return <ul>{listItems}</ul>; }
Захаванне парадку элементаў спісу з дапамогай key
Звярніце ўвагу, што ўсе пясочніцы вышэй паказваюць памылку ў кансолі:
Каб выправіць гэту памылку трэба прысвоіць кожнаму элементу масіву ключ (key
) — радок або лік, які адназначна ідэнтыфікуе яго сярод іншых элементаў у гэтым масіве:
<li key={person.id}>...</li>
Ключы паведамляюць React, якому элементу масіву адпавядае кожны кампанент, каб потым ён мог іх супаставіць. Гэта важна, калі элементы масіву могуць перамяшчацца (напрыклад, з-за сартавання), устаўляцца або выдаляцца. Добра падабраны key
дапамагае React зразумець, што менавіта адбылося, і зрабіць правільныя абнаўленні ў дрэве DOM.
Замест таго, каб генераваць ключы на хаду, вы павінны ўключыць іх у свае даныя:
export const people = [{ id: 0, // Выкарыстоўваецца як ключ у JSX name: 'Крэола Кэтрын Джонсан', profession: 'матэматык', accomplishment: 'разлікі для касмічных палётаў', imageId: 'MK3eW3A' }, { id: 1, // Выкарыстоўваецца як ключ у JSX name: 'Марыа Хасэ Маліна-Паскель Энрыкес', profession: 'хімік', accomplishment: 'адкрыццё арктычнай азонавай дзіркі', imageId: 'mynHUSa' }, { id: 2, // Выкарыстоўваецца як ключ у JSX name: 'Махамад Абдус Салам', profession: 'фізік', accomplishment: 'тэорыя электрамагнетызму', imageId: 'bE7W1ji' }, { id: 3, // Выкарыстоўваецца як ключ у JSX name: 'Персі Лавон Джуліан', profession: 'хімік', accomplishment: 'піянер у вытворчасці картызону, стэроідаў і супрацьзачаткавых таблетак', imageId: 'IOjWm71' }, { id: 4, // Выкарыстоўваецца як ключ у JSX name: 'Субрахманьян Чандрасекар', profession: 'астрафізік', accomplishment: 'разлік масы белага карліка', imageId: 'lrWQx8l' }];
Deep Dive
Што рабіць, калі кожны элемент павінен адлюстроўваць не адзін, а некалькі вузлоў DOM?
Скарочаны сінтаксіс фрагмента <>...</>
не дазволіць вам перадаць ключ, таму вам трэба альбо згрупаваць іх у адзін <div>
, альбо выкарыстоўваць крыху даўжэйшы і больш выразны сінтаксіс <Fragment>
:
import { Fragment } from 'react';
// ...
const listItems = people.map(person =>
<Fragment key={person.id}>
<h1>{person.name}</h1>
<p>{person.bio}</p>
</Fragment>
);
Фрагменты знікаюць з DOM, так што гэта створыць плоскі спіс <h1>
, <p>
, <h1>
, <p>
і г.д.
Дзе ўзяць key
Розныя крыніцы даных даюць розныя крыніцы ключоў:
- Даныя з базы даных: Калі вашы даныя прыходзяць з базы даных, вы можаце выкарыстоўваць ключы/ID з базы даных, якія па сваёй прыродзе з’яўляюцца ўнікальнымі.
- Лакальна згенераваныя даныя: Калі вашы даныя згенерыраваны і захоўваюцца лакальна (напрыклад, нататкі ў праграме для вядзення нататак), выкарыстоўвайце інкрэментны лічыльнік
crypto.randomUUID()
або пакетuuid
пры стварэнні элементаў.
Правілы ключоў
- Ключы павінны быць унікальнымі сярод сваіх суседніх элементаў. Аднак, можна выкарыстоўваць аднолькавыя ключы для JSX вузлоў у розных масівах.
- Ключы не павінны мяняцца паколькі гэта пазбаўляе іх сэнсу! Не генеруйце іх падчас рэндэрынгу.
Навошта React патрэбны ключы?
Уявіце, што файлы на вашым працоўным стале не маюць імёнаў. Замест гэтага вы б спасылаліся на іх па парадку - першы файл, другі файл і г.д. Магчыма да гэтага і можна прызвычаіцца, але калі вы выдаліце які-небудзь файл, парадак зменіцца і ўсё стане заблытаным. Другі файл стане першым файлам, трэці файл будзе другім файлам і г.д.
Імёны файлаў у папцы і JSX ключы ў масіве маюць падобную мэту. Яны дазваляюць нам адрозніваць элементы ад іншых элементаў у масіве. Добра падабраны ключ дае больш інфармацыі, чым пазіцыя ў масіве. Нават калі пазіцыя мяняецца з-за змены парадку, key
дазваляе React ідэнтыфікаваць элемент на працягу ўсяго яго існавання.
Recap
На гэтай старонцы вы даведаліся:
- Як перамясціць даныя з кампанентаў у такія структуры даных, як масівы і аб’екты.
- Як стварыць наборы падобных кампанентаў з дапамогай JavaScript метаду
map()
. - Як ствараць масівы адфільтраваных элементаў з дапамогай JavaScript метаду
filter()
. - Навошта і як задаваць
key
для кожнага кампанента ў калекцыі, каб React мог адсочваць кожны з іх, нават калі іх пазіцыя або даныя змяняюцца.
Challenge 1 of 4: Падзел спісу на два
У гэтым прыкладзе паказаны спіс усіх людзей.
Змяніце яго так, каб паказаць два асобныя спісы адзін за адным: Хімікі і Усе астатнія. Як і раней, вы можаце вызначыць, ці з’яўляецца чалавек хімікам, праверыўшы person.profession === 'хімік'
.
import { people } from './data.js'; import { getImageUrl } from './utils.js'; export default function List() { const listItems = people.map(person => <li key={person.id}> <img src={getImageUrl(person)} alt={person.name} /> <p> <b>{person.name}:</b> {' ' + person.profession}. Галоўнае дасягненне: {person.accomplishment} </p> </li> ); return ( <article> <h1>Навукоўцы</h1> <ul>{listItems}</ul> </article> ); }