Ku-render Orodha

Mara nyingi utataka kuonyesha components (vipengele) kadhaa zinazofanana kutoka kwenye mkusanyiko wa data. Unaweza kutumia mbinu za array za JavaScript kuchakata array ya data. Kwenye ukurasa huu, utatumia filter() na map() pamoja na React ili kuchuja na kubadilisha array yako ya data kuwa array ya components.

You will learn

  • Jinsi ya ku-render components kutoka kwenye array ukitumia map() ya JavaScript
  • Jinsi ya ku-render components mahususi tu ukitumia filter() ya JavaScript
  • Wakati na sababu ya kutumia keys za React

Ku-render data kutoka kwenye arrays

Tuseme una orodha ya maudhui.

<ul>
<li>Creola Katherine Johnson: mathematician</li>
<li>Mario José Molina-Pasquel Henríquez: chemist</li>
<li>Mohammad Abdus Salam: physicist</li>
<li>Percy Lavon Julian: chemist</li>
<li>Subrahmanyan Chandrasekhar: astrophysicist</li>
</ul>

Tofauti pekee kati ya vipengele hivyo vya orodha ni maudhui yao, data yao. Mara nyingi utahitaji kuonyesha nakala kadhaa za component ileile ukitumia data tofauti wakati unajenga violesura: kutoka orodha za maoni hadi maghala ya picha za profaili. Katika hali hizi, unaweza kuhifadhi data hiyo katika objects na arrays za JavaScript na kutumia mbinu kama map() na filter() ili ku-render orodha za components kutoka humo.

Huu hapa ni mfano mfupi wa jinsi ya kuzalisha orodha ya vipengele kutoka kwenye array:

  1. Hamisha data hiyo kwenye array:
const people = [
'Creola Katherine Johnson: mathematician',
'Mario José Molina-Pasquel Henríquez: chemist',
'Mohammad Abdus Salam: physicist',
'Percy Lavon Julian: chemist',
'Subrahmanyan Chandrasekhar: astrophysicist'
];
  1. Map wanachama wa people kuwa array mpya ya vipengele vya JSX, listItems:
const listItems = people.map(person => <li>{person}</li>);
  1. Rudisha listItems kutoka kwenye component yako ikiwa imefungwa ndani ya <ul>:
return <ul>{listItems}</ul>;

Huu hapa ni matokeo:

const people = [
  'Creola Katherine Johnson: mathematician',
  'Mario José Molina-Pasquel Henríquez: chemist',
  'Mohammad Abdus Salam: physicist',
  'Percy Lavon Julian: chemist',
  'Subrahmanyan Chandrasekhar: astrophysicist'
];

export default function List() {
  const listItems = people.map(person =>
    <li>{person}</li>
  );
  return <ul>{listItems}</ul>;
}

Angalia kuwa sanduku la mchanga (sandbox) hapo juu linaonyesha hitilafu ya console:

Console
Warning: Each child in a list should have a unique “key” prop.

Utajifunza jinsi ya kurekebisha hitilafu hii baadaye kwenye ukurasa huu. Kabla hatujafika hapo, hebu tuongeze muundo fulani kwenye data yako.

Kuchuja arrays za vipengele

Data hii inaweza kupangwa kwa muundo zaidi.

const people = [{
id: 0,
name: 'Creola Katherine Johnson',
profession: 'mathematician',
}, {
id: 1,
name: 'Mario José Molina-Pasquel Henríquez',
profession: 'chemist',
}, {
id: 2,
name: 'Mohammad Abdus Salam',
profession: 'physicist',
}, {
id: 3,
name: 'Percy Lavon Julian',
profession: 'chemist',
}, {
id: 4,
name: 'Subrahmanyan Chandrasekhar',
profession: 'astrophysicist',
}];

Tuseme unataka njia ya kuonyesha watu tu ambao taaluma yao ni 'chemist'. Unaweza kutumia mbinu ya filter() ya JavaScript kurudisha watu hao tu. Mbinu hii huchukua array ya vipengele, huvipitisha kupitia “jaribio” (function inayorudisha true au false), na hurudisha array mpya ya vipengele vile tu vilivyofaulu jaribio (vilivyorudisha true).

Unataka tu vile vipengele ambavyo profession yake ni 'chemist'. Function ya “jaribio” ya hili inaonekana kama (person) => person.profession === 'chemist'. Hivi ndivyo ya kuiunganisha pamoja:

  1. Tengeneza array mpya ya watu “chemist” tu, chemists, kwa kuita filter() kwenye people ukichuja kwa person.profession === 'chemist':
const chemists = people.filter(person =>
person.profession === 'chemist'
);
  1. Sasa map juu ya chemists:
const listItems = chemists.map(person =>
<li>
<img
src={getImageUrl(person)}
alt={person.name}
/>
<p>
<b>{person.name}:</b>
{' ' + person.profession + ' '}
maarufu kwa {person.accomplishment}
</p>
</li>
);
  1. Mwisho, rudisha listItems kutoka kwenye component yako:
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 === 'chemist'
  );
  const listItems = chemists.map(person =>
    <li>
      <img
        src={getImageUrl(person)}
        alt={person.name}
      />
      <p>
        <b>{person.name}:</b>
        {' ' + person.profession + ' '}
        maarufu kwa {person.accomplishment}
      </p>
    </li>
  );
  return <ul>{listItems}</ul>;
}

Pitfall

Arrow functions hurudisha kwa siri expression iliyo mara tu baada ya =>, hivyo hukuhitaji kauli ya return:

const listItems = chemists.map(person =>
<li>...</li> // Kurudisha kwa siri!
);

Hata hivyo, lazima uandike return waziwazi ikiwa => yako inafuatwa na kufunga kwa mabano ya curly {!

const listItems = chemists.map(person => { // Mabano ya curly
return <li>...</li>;
});

Arrow functions zenye => { husemekana kuwa na “block body”. Hukuruhusu kuandika zaidi ya mstari mmoja wa msimbo, lakini lazima uandike kauli ya return mwenyewe. Ukiisahau, hakuna kitakachorudishwa!

Kuweka vipengele vya orodha katika mpangilio kwa key

Angalia kuwa masanduku yote ya mchanga hapo juu yanaonyesha hitilafu kwenye console:

Console
Warning: Each child in a list should have a unique “key” prop.

Unahitaji kumpa kila kipengele cha array key — mfululizo wa herufi au nambari inayokitambulisha kwa upekee miongoni mwa vipengele vingine katika array hiyo:

<li key={person.id}>...</li>

Note

Elementi za JSX zilizo moja kwa moja ndani ya wito wa map() daima zinahitaji keys!

Keys huiambia React ni kipengele kipi cha array kila component kinacholingana nacho, ili iweze kuzilinganisha baadaye. Hili huwa muhimu ikiwa vipengele vya array yako vinaweza kuhama (mfano kutokana na kupanga), kuingizwa, au kufutwa. key iliyochaguliwa vizuri humsaidia React kubaini kwa hakika kilichotokea, na kufanya masasisho sahihi kwenye mti (tree) wa DOM.

Badala ya kuzalisha keys papo hapo, unapaswa kuzijumuisha ndani ya data yako:

export const people = [{
  id: 0, // Inatumika katika JSX kama key
  name: 'Creola Katherine Johnson',
  profession: 'mathematician',
  accomplishment: 'spaceflight calculations',
  imageId: 'MK3eW3A'
}, {
  id: 1, // Inatumika katika JSX kama key
  name: 'Mario José Molina-Pasquel Henríquez',
  profession: 'chemist',
  accomplishment: 'discovery of Arctic ozone hole',
  imageId: 'mynHUSa'
}, {
  id: 2, // Inatumika katika JSX kama key
  name: 'Mohammad Abdus Salam',
  profession: 'physicist',
  accomplishment: 'electromagnetism theory',
  imageId: 'bE7W1ji'
}, {
  id: 3, // Inatumika katika JSX kama key
  name: 'Percy Lavon Julian',
  profession: 'chemist',
  accomplishment: 'pioneering cortisone drugs, steroids and birth control pills',
  imageId: 'IOjWm71'
}, {
  id: 4, // Inatumika katika JSX kama key
  name: 'Subrahmanyan Chandrasekhar',
  profession: 'astrophysicist',
  accomplishment: 'white dwarf star mass calculations',
  imageId: 'lrWQx8l'
}];

Deep Dive

Kuonyesha nodi kadhaa za DOM kwa kila kipengele cha orodha

Unafanyaje wakati kila kipengele kinahitaji ku-render si nodi moja ya DOM, bali kadhaa?

Sintaksia fupi ya Fragment <>...</> haitakuruhusu kupitisha key, hivyo unahitaji ama kuvikusanya ndani ya <div> moja, au kutumia sintaksia ndefu kidogo na wazi zaidi ya <Fragment>:

import { Fragment } from 'react';

// ...

const listItems = people.map(person =>
<Fragment key={person.id}>
<h1>{person.name}</h1>
<p>{person.bio}</p>
</Fragment>
);

Fragments hutoweka kutoka kwenye DOM, hivyo hii itazalisha orodha bapa ya <h1>, <p>, <h1>, <p>, na kadhalika.

Wapi pa kupata key yako

Vyanzo tofauti vya data hutoa vyanzo tofauti vya keys:

  • Data kutoka kwenye database: Ikiwa data yako inatoka kwenye database, unaweza kutumia keys/IDs za database, ambazo ni za kipekee kwa asili yake.
  • Data iliyozalishwa kienyeji: Ikiwa data yako imezalishwa na kuhifadhiwa kienyeji (mfano madokezo katika programu ya kuchukua madokezo), tumia kihesabu kinachoongezeka, crypto.randomUUID() au kifurushi kama uuid wakati wa kutengeneza vipengele.

Kanuni za keys

  • Keys lazima ziwe za kipekee miongoni mwa ndugu. Hata hivyo, ni sawa kutumia keys zilezile kwa nodi za JSX katika arrays tofauti.
  • Keys hazipaswi kubadilika ama hilo linaharibu kusudi lao! Usizizalishe wakati wa ku-render.

Kwa nini React inahitaji keys?

Fikiria kwamba faili kwenye desktop yako hazikuwa na majina. Badala yake, ungezirejelea kwa mpangilio wao — faili ya kwanza, faili ya pili, na kadhalika. Ungeweza kuzoea, lakini mara tu unapofuta faili, ingekuwa jambo la kutatanisha. Faili ya pili ingekuwa faili ya kwanza, faili ya tatu ingekuwa faili ya pili, na kadhalika.

Majina ya faili katika folda na keys za JSX katika array hutimiza kusudi linalofanana. Hutuwezesha kukitambulisha kipengele kwa upekee kati ya ndugu zake. key iliyochaguliwa vizuri hutoa taarifa zaidi kuliko nafasi ndani ya array. Hata kama nafasi itabadilika kutokana na kupanga upya, key humwezesha React kukitambua kipengele katika maisha yake yote.

Pitfall

Huenda ukashawishika kutumia index ya kipengele katika array kama key yake. Kwa kweli, hicho ndicho React itatumia ikiwa hutabainisha key hata kidogo. Lakini mpangilio ambao unavyo-render vipengele utabadilika baada ya muda ikiwa kipengele kitaingizwa, kufutwa, au ikiwa array itapangwa upya. Index kama key mara nyingi husababisha hitilafu (bugs) za hila na za kutatanisha.

Vivyo hivyo, usizalishe keys papo hapo, mfano kwa key={Math.random()}. Hii itasababisha keys kutolingana kamwe kati ya renders, ikipelekea components zako zote na DOM kuundwa upya kila mara. Si tu kwamba hili ni la polepole, bali pia litapoteza input yoyote ya mtumiaji ndani ya vipengele vya orodha. Badala yake, tumia ID thabiti inayotegemea data.

Kumbuka kuwa components zako hazitapokea key kama prop. Inatumika tu kama kidokezo na React yenyewe. Ikiwa component yako inahitaji ID, lazima uipitishe kama prop tofauti: <Profile key={id} userId={id} />.

Recap

Kwenye ukurasa huu ulijifunza:

  • Jinsi ya kuhamisha data nje ya components na kuiweka katika miundo ya data kama arrays na objects.
  • Jinsi ya kuzalisha seti za components zinazofanana kwa map() ya JavaScript.
  • Jinsi ya kutengeneza arrays za vipengele vilivyochujwa kwa filter() ya JavaScript.
  • Kwa nini na jinsi ya kuweka key kwenye kila component katika mkusanyiko ili React iweze kufuatilia kila mojawapo hata kama nafasi au data yao itabadilika.

Challenge 1 of 4:
Kugawanya orodha kuwa mbili

Mfano huu unaonyesha orodha ya watu wote.

Ubadilishe ili uonyeshe orodha mbili tofauti moja baada ya nyingine: Chemists na Everyone Else. Kama ilivyo awali, unaweza kubaini iwapo mtu ni chemist kwa kuangalia kama person.profession === 'chemist'.

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 + ' '}
        maarufu kwa {person.accomplishment}
      </p>
    </li>
  );
  return (
    <article>
      <h1>Scientists</h1>
      <ul>{listItems}</ul>
    </article>
  );
}