ການສະແດງ Lists

ທ່ານຈະຕ້ອງການສະແດງ component ທີ່ຄ້າຍກັນຈາກຂໍ້ມູນຂອງ collection. ທ່ານສາມາດໃຊ້ JavaScript array methods ເພື່ອຈັດການ array ຂອງຂໍ້ມູນ. ໃນ page ນີ້, ທ່ານຈະໄດ້ໃຊ້ filter() ແລະ map() ດ້ວຍ React ເພື່ອ filter ແລະ ແປງ array ຂໍ້ມູນຂອງທ່ານໃຫ້ເປັນ array ຂອງ component.

You will learn

  • ວິທີການສະແດງ component ຈາກ array ໂດຍໃຊ້ map() ຂອງ JavaScript
  • ວິທີການສະແດງສະເພາະ component ໂດຍໃຊ້ filter() ຂອງ JavaScript
  • ເມື່ອໃດ ແລະ ເປັນຫຍັງຕ້ອງໃຊ້ React keys

ການສະແດງຂໍ້ມູນຈາກ arrays

ບອກວ່າທ່ານມີລາຍການຂອງເນື້ອຫາ.

<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>

ຂໍ້ແຕກຕ່າງລະຫວ່າງລາຍການເຫຼົ່ານີ້ແມ່ນເນື້ອຫາ ແລະ ຂໍ້ມູນ. ທ່ານຈະຕ້ອງສະແດງ component ດຽວກັນຫຼາຍລາຍການໂດຍໃຊ້ຂໍ້ມູນທີ່ແຕກຕ່າງກັນເມື່ອສ້າງ interface: ຈາກລາຍການ comment ໄປຈົນເຖິງ gallery ຮູບພາບ profile. ໃນກໍລະນີນີ້, ທ່ານສາມາດເກັບຂໍ້ມູນໃນ object JavaScript ແລະ array ແລະ ໃຊ້ method ເຊັ່ນ map() ແລະ filter() ເພື່ອສະແດງລາຍການຂອງ component ຈາກມັນ.

ນີ້ແມ່ນຕົວຢ່າງຂອງວິທີສ້າງລາຍການຈາກ array:

  1. ຍ້າຍ ຂໍ້ມູນໄປເປັນ 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 member people ໄປເປັນ array ໃໝ່ຂອງ node JSX, listItems:
const listItems = people.map(person => <li>{person}</li>);
  1. Return listItems ຈາກ component ທີລວມຢູ່ໃນ <ul>:
return <ul>{listItems}</ul>;

ນີ້ແມ່ນຜົນລັບ:

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

ສັງເກດ sandbox ດ້ານເທິງສະແດງ console error:

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

ທ່ານຈະໄດ້ຮຽນວິທີແກ້ໄຂຂໍ້ຜິດພາດນີ້ໃນພາຍຫຼັງ. ກ່ອນຈະຮອດຂັ້ນຕອນນັ້ນ, ມາເພີ່ມໂຄ່ງສ້າງສຳລັບຂໍ້ມູນຂອງທ່ານ.

ການ filter array ຂອງລາຍການ

ຂໍ້ມູນນີ້ສາມາດຈັດໂຄ່ງສ້າງໄດ້ຫຼາຍຂຶ້ນ.

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',
}, {
name: 'Percy Lavon Julian',
profession: 'chemist',
}, {
name: 'Subrahmanyan Chandrasekhar',
profession: 'astrophysicist',
}];

ສົມມຸດວ່າທ່ານຕ້ອງການວິທີສະແດງສະເພາະຄົນທີ່ມີອາຊີບເປັນ 'chemist'. ທ່ານສາມາດໃຊ້ method JavaScript filter() ເພື່ອ return ສະເພາະແຕ່ຜູ້ຄົນເຫຼົ່ານັ້ນ. Method ນີ້ໃຊ້ array ຂອງລາຍການ, ສົ່ງຜ່ານ “test” (ຟັງຊັ່ນທີ່ returns true ຫຼື false), ແລະ return array ໃໝ່ສະເພາະລາຍການທີ່ຜ່ານການ test (returned true).

ທ່ານຕ້ອງການສະເພາະລາຍການທີ່ profession ເປັນ chemist ເທົ່ານັ້ນ. ຟັງຊັ່ນ “test” ຈະມີລັກສະນະດັ່ງນີ້ (person) => person.profession === 'chemist'. ນີ້ແມ່ນວິທີການລວມເຂົ້າກັນ:

  1. ສ້າງ array ໃໝ່ທີ່ມີແຕ່ຄົນເປັນ “chemist”, chemists, ໂດຍການໃຊ້ filter() ໃນ people filter ໂດຍ person.profession === 'chemist':
const chemists = people.filter(person =>
person.profession === 'chemist'
);
  1. ທຳການ map ເທິງ chemists:
const listItems = chemists.map(person =>
<li>
<img
src={getImageUrl(person)}
alt={person.name}
/>
<p>
<b>{person.name}:</b>
{' ' + person.profession + ' '}
known for {person.accomplishment}
</p>
</li>
);
  1. ສຸດທ້າຍ, return listItems ຈາກ component ຂອງທ່ານ:
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 + ' '}
        known for {person.accomplishment}
      </p>
    </li>
  );
  return <ul>{listItems}</ul>;
}

Pitfall

Arrow ຟັງຊັ່ນຈະ return expression ທັນທີຫຼັງຈາກ =>, ສະນັ້ນທ່ານບໍ່ຈຳເປັນຕ້ອງໃຊ້ return statement:

const listItems = chemists.map(person =>
<li>...</li> // Implicit return!
);

ເຖິງຢ່າງໃດກໍຕາມ, ທ່ານຕ້ອງຂຽນ return ທັນທີຖ້າ => ທ່ານຕາມຫຼັງດ້ວຍ { ວົງປີກກາ!

const listItems = chemists.map(person => { // Curly brace
return <li>...</li>;
});

Arrow ຟັງຊັ່ນປະກອບມີ => { ແມ່ນຖືກເອີ້ນວ່າ “block body”. ມັນເຮັດໃຫ້ທ່ານສາມາດຂຽນ code ໄດ້ຫຼາຍກວ່າແຖວດຽວ, ແຕ່ວ່າທ່ານ ຕ້ອງ ໄດ້ຂຽນ return statement ດ້ວຍໂຕເອງ. ຖ້າທ່ານລືມ, ຈະບໍ່ມີຫຍັງຖືກ return!

ການຈັດລະບຽບລາຍການດ້ວຍ key

ສັງເກດວ່າ sandbox ທັງໝົດດ້ານເທິງສະແດງຂໍ້ຜິດພາດໃນ console:

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

ທ່ານຕ້ອງໄດ້ໃສ່ key ໃນແຕ່ລະລາຍການຂອງ array — string ຫຼື number ທີ່ບໍ່ຊໍ້າກັບລາຍການອື່ນໆໃນ array ນັ້ນ:

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

Note

element JSX ໂດຍກົງພາຍໃນການເອີ້ນ map() ຕ້ອງການ key ສະເໝີ!

Key ຈະບອກ React ວ່າລາຍການ array ໃດທີ່ແຕ່ລະ component ສຳພັນກັນ, ເພື່ອໃຫ້ສາມາດຈັບຄູ່ໄດ້ໃນພາຍຫຼັງ. ນີ້ມີຄວາມສຳຄັນຫຼາຍຖ້າລາຍການ array ຂອງທ່ານສາມາດຍ້າຍ (ຕົວຢ່າງ ເນື່ອງຈາກການຮຽງລຳດັບ), ເພີ່ມ, ຫຼື ຖືກລຶບ. ການເລືອກ key ທີ່ດີສາມາດຊ່ວຍໃຫ້ React ສະຫຼຸບສິ່ງທີ່ເກີດຂຶ້ນແທ້, ແລະ ທຳການອັບເດດທີ່ຖືກຕ້ອງກັບ DOM tree.

ແທນທີ່ຈະສ້າງ key ທັນທີ, ທ່ານຄວນລວມມັນໄວ້ໃນຂໍ້ມູນຂອງທ່ານ:

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

Deep Dive

ການສະແດງຫຼາຍ DOM node ສຳລັບແຕ່ລະລາຍການ

ທ່ານຈະເຮັດແນວໃດເມືອແຕ່ລະລາຍການບໍ່ຈຳເປັນຕ້ອງສະແດງພຽງ node ດຽວ, ແຕ່ຕ້ອງມີຫຼາຍ DOM node?

Syntax ສັ້ນ <>...</> Fragment ບໍ່ອະນຸຍາດໃຫ້ທ່ານສົ່ງ key, ສະນັ້ນທ່ານຕ້ອງ group ເຂົ້າເປັນ <div> ດຽວ, ຫຼື ໃຊ້ syntax ທີ່ຍາວຂຶ້ນໜ້ອຍໜຶ່ງ ແລະ ຊັດເຈນຫຼາຍຂຶ້ນ <Fragment>:

import { Fragment } from 'react';

// ...

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

Fragment ຫາຍໄປຈາກ DOM, ສະນັ້ນ, ນີ້ຈະສ້າງລາຍການຂອງ <h1>, <p>, <h1>, <p>, ແລະ ອື່ນໆ.

ຈະຫາ key ໄດ້ຈາກບ່ອນໃດ

ແຫຼ່ງຂອງຂໍ້ມູນທີ່ແຕກຕ່າງໃຫ້ແຫຼ່ງທີ່ມາຂອງ key ທີ່ຕ່າງກັນ:

  • ຂໍ້ມູນຈາກຖານຂໍ້ມູນ: ຖ້າຂໍ້ມູນຂອງທ່ານແມ່ນມາຈາກຖານຂໍ້ມູນ, ທ່ານສາມາດໃຊ້ keys/IDs ຖານຂໍ້ມູນ, ທີ່ບໍ່ຊໍ້າກັນໂດຍທຳມະຊາດ.
  • ຂໍ້ມູນທີ່ສ້າງຂຶ້ນພາຍໃນເຄື່ອງ: ຫາກຂໍ້ມູນຂອງທ່ານຖືກສ້າງຂຶ້ນ ແລະ ມີຢູ່ໃນເຄື່ອງ (ເຊັ່ນ: ບັນທຶກໃນແອັບຈົດບັນທຶກ), ໃຫ້ໃຊ້ໂຕນັບທີ່ເພີ່ມຂື້ນ crypto.randomUUID() ຫຼື package ເຊັ່ນ uuid ເມື່ອສ້າງລາຍການ.

ກົດຂອງ keys

  • Key ຕ້ອງບໍ່ຊໍ້າກັນທຽບກັບໂຕອື່ນ. ເຖິງຢ່າງໃດກໍຕາມ, ເປັນເລື່ອງປົກະຕິທີ່ຈະໃຊ້ key ດຽວກັນສຳລັບ JSX node ໃນ array ທີ່ແຕກຕ່າງກັນ.
  • Key ຕ້ອງບໍ່ປ່ຽນແປງ ຫຼື ຜິດຈຸດປະສົງ! ຢ່າສ້າງມັນໃນຕອນທີ່ກຳລັງສະແດງຜົນ.

ເປັນຫຍັງ React ຕ້ອງການ key?

ຈິນຕະນາການວ່າຟາຍຢູ່ desktop ຂອງທ່ານບໍ່ມີຊື່. ແຕ່ທ່ານຄວນອ້າງອີງເຖິງມັນຕາມລຳດັບ —ຟາຍທຳອິດ, ຟາຍທີ່ສອງ, ແລະ ອື່ນໆ. ທ່ານອາດຈະລຶ້ງກັບມັນ, ແຕ່ເມື່ອທ່ານລຶບຟາຍ, ມັນຈະເຮັດໃຫ້ສັບສົນ. ຟາຍທີ່ສອງຈະກາຍເປັນຟາຍທຳອິດ, ຟາຍທີ່ສາມຈະກາຍເປັນຟາຍທີ່ສອງ ແລະ ອື່ນໆ.

ຊື່ຟາຍໃນໂຟນເດີ ແລະ key JSX ໃນ array ມີຈຸດປະສົງຄ້າຍຄືກັນ. ມັນລະບຸລາຍການລະຫວ່າງກັນໂດຍບໍ່ຊໍ້າກັນ. Key ທີ່ເລືອກມາຢ່າງດີຈະໃຫ້ຂໍ້ມູນຫຼາຍກວ່າຕຳແໜ່ງພາຍໃນ array. ເຖິງວ່າ ຕຳແໜ່ງ ຈະປ່ຽນໄປເນື່ອງຈາກການຮຽງລຳດັບໃໝ່ key ຈະຊ່ວຍໃຫ້ React ກຳນົດລາຍການໄດ້ຕະຫຼອດອາຍຸການໃຊ້ງານ.

Pitfall

ທ່ານອາດຫຼົງໃຊ້ index ຂອງລາຍການເປັນ key. ໃນຄວາມເປັນຈິງ,​ React ຈະໃຊ້ຖ້າທ່ານບໍ່ໄດ້ກຳນົດ key ເລີຍ. ແຕ່ລຳດັບທີ່ທ່ານສະແດງລາຍການຈະປ່ຽນໄປເມື່ອເວລາຜ່ານໄປຖ້າລາຍການຖືກເພີ່ມ, ລຶບ ຫຼື ຖ້າ array ຖືກການຈັດລຳດັບໃໝ່. Index ທີ່ເປັນ key ສ່ວນຫຼາຍຈະເຮັດໃຫ້ເກີດບັນຫາ ແລະ ຍາກໃນການນຳຫາຂໍ້ຜິດພາດ.

ເຊັ່ນດຽວກັນ, ບໍ່ສ້າງ key ທັນທີ, ຕົວຢ່າງ ດ້ວຍ key={Math.random()}. ນີ້ຈະເຮັດໃຫ້ key ບໍ່ກົງກັນໃນລະຫວ່າງການສະແດງຜົນ, ເຮັດໃຫ້ component ທັງໝົດຂອງທ່ານ ແລະ DOM ຖືກສ້າງຂຶ້ນໃໝ່ທຸກຄັ້ງ. ບໍ່ພຽງແຕ່ຈະຊ້າເທົ່ານັ້ນ, ແຕ່ມັນຍັງຈະເສຍ user input ພາຍໃນລາຍການນຳອີກ. ໃຫ້ໃຊ້ ID ທີ່ສະຖຽນຕາມຂໍ້ມູນແທນ.

ສັງເກດວ່າ Component ຂອງທ່ານຈະບໍ່ໄດ້ຮັບ key ເປັນ prop. ມັນຈະໃຊ້ເປັນພຽງ hint ໂດຍ React ເອງ. ຖ້າ Component ທ່ານຕ້ອງການ ID, ທ່ານຕ້ອງໄດ້ສົ່ງເປັນ prop ແຍກຕ່າງຫາກ: <Profile key={id} userId={id} />.

Recap

ໃນ page ນີ້ທ່ານໄດ້ຮຽນ:

  • ວິທີຍ້າຍຂໍ້ມູນອອກຈາກ component ແລະ ເຂົ້າສູ່ໂຄ່ງສ້າງຂໍ້ມູນເຊັ່ນ array ແລະ object.
  • ວິທີສ້າງຊຸດຂອງ component ທີ່ຄ້າຍຄືກັນດ້ວຍ map() ຂອງ JavaScript.
  • ວິທີສ້າງ array ຂອງລາຍການທີ່ filter ດ້ວຍ filter() ຂອງ JavaScript.
  • ເຫດຜົນທີ່ຕ້ອງຕັ້ງຄ່າ key ໃນແຕ່ລະ component ໃນ collection ເພື່ອໃຫ້ React ສາມາດຕິດຕາມແຕ່ລະ component ໄດ້ເຖິງວ່າຕຳແໜ່ງ ຫຼື ຂໍ້ມູນຈະມີການປ່ຽນແປງ.

Challenge 1 of 4:
ການແຍກ list ອອກເປັນສອງສ່ວນ

ຕົວຢ່າງນີ້ສະແດງລາຍການຂອງ people ທັງໝົດ.

ປ່ຽນມັນເພື່ອສະແດງລາຍການແຍກກັນສອງລາຍການ: Chemist ແລະ Everyone Else. ຄືກັນກັບກ່ອນໜ້ານີ້, ທ່ານສາມາດກຳນົດໄດ້ວ່າບຸກຄົນເຫຼົ່ານີ້ເປັນ chemist ໂດຍການກວດວ່າ 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 + ' '}
        known for {person.accomplishment}
      </p>
    </li>
  );
  return (
    <article>
      <h1>Scientists</h1>
      <ul>{listItems}</ul>
    </article>
  );
}