ການສົ່ງ Props ໄປຫາ Component

Component React ໃຊ້ props ເພື່ອສື່ສານລະຫວ່າງກັນ ແລະ ກັນ. ທຸກໆ parent component ສາມາດສົ່ງບາງຂໍ້ມູນໄປຫາ child component ມັນເອງໂດຍການໃຫ້ props. Props ອາດເຕືອນທ່ານກ່ຽວກັບ attribute HTML, ແຕ່ທ່ານສາມາດສົ່ງຄ່າຂອງ JavaScript ໃດກໍໄດ້ຜ່ານມັນລວມເຖິງ objects, arrays, ແລະ ຟັງຊັ່ນ.

You will learn

  • ວິທີສົ່ງ props ໄປຫາ component
  • ວິທີອ່ານ props ຈາກ component
  • ວິທີກຳນົດຄ່າເລີ່ມຕົ້ນສຳລັບ props
  • ວິທີສົ່ງບາງ JSX ໄປຫາ component
  • ວິທີທີ່ props ປ່ຽນແປງຕະຫຼອດເວລາ

ຄຸ້ນເຄີຍກັບ props

Props ແມ່ນຂໍ້ມູນທີ່ທ່ານສົ່ງຜ່ານແທັກ JSX. ຕົວຢ່າງ, className, src, alt, width, ແລະ height ແມ່ນບາງ props ທີ່ທ່ານສາມາດສົ່ງຜ່ານ <img>:

function Avatar() {
  return (
    <img
      className="avatar"
      src="https://i.imgur.com/1bX5QH6.jpg"
      alt="Lin Lanying"
      width={100}
      height={100}
    />
  );
}

export default function Profile() {
  return (
    <Avatar />
  );
}

Props ສາມາດສົ່ງຜ່ານແທັກ <img> ນັ້ນຖືກກຳນົດແລ້ວ (ReactDOM conforms to the HTML standard). ແຕ່ທ່ານສາມາດສົ່ງ props ໃດກໍ່ໄດ້ໄປຫາ component ຂອງທ່ານເອງ, ເຊັ່ນ <Avatar>, ເພື່ອປັບແຕ່ງ. ນີ້ແມ່ນວິທີ!

ການສົ່ງ props ໄປຫາ component

ໃນ code ນີ້, Component Profile ບໍ່ສາມາດສົ່ງ props ໃດກໍໄດ້ໄປຫາ child component, Avatar:

export default function Profile() {
return (
<Avatar />
);
}

ທ່ານສາມາດໃຫ້ props Avatar ໃນສອງຂັ້ນຕອນ.

ຂັ້ນຕອນທີ 1: ສົ່ງ props ໄປຫາ child component

ທຳອິດ, ສົ່ງ props ໄປຫາ Avatar. ຕົວຢ່າງ, ສົ່ງ 2 props: person (ເປັນ object), ແລະ size (ເປັນ number):

export default function Profile() {
return (
<Avatar
person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
size={100}
/>
);
}

Note

ຖ້າສອງວົງປີກກາຢູ່ຫຼັງ person= ເຮັດໃຫ້ທ່ານສັບສົນ, ໃຫ້ຈື່ໄວ້ວ່າ ມັນເປັນ object ຢູ່ພາຍໃນວົງປີກກາ JSX.

ທ່ານສາມາດອ່ານ props ນີ້ພາຍໃນ component Avatar

ຂັ້ນຕອນທີ 2: ການອ່ານ props ພາຍໃນ child component

ທ່ານສາມາດອ່ານ props ໂດຍລະບຸຊື່ person, size ແຍກກັນໂດຍໃສ່ເຄື່ອງໝາຍຈຸດພາຍໃນ ({ ແລະ }) ໂດຍກົງຫຼັງຈາກ function Avatar. ນີ້ເຮັດໃຫ້ທ່ານສາມາດນຳໃຊ້ພາຍໃນ code Avatar, ຄືກັບທີທ່ານໃຊ້ກັບຕົວແປ.

function Avatar({ person, size }) {
// person and size are available here
}

ເພີ່ມ logic ໃສ່ Avatar ທີ່ໃຊ້ props person ແລະ size ສຳລັບການສະແດງຜົນເທົ່ານີ້ກໍສຳເລັດ.

ຕອນນີ້ທ່ານສາມາດຕັ້ງຄ່າ Avatar ເພື່ອສະແດງໄດ້ຫຼາຍວິທີດ້ວຍຫຼາຍ prop ທີ່ແຕກຕ່າງກັນ. ລອງປັບຫຼິ້ນເບິ່ງ!

import { getImageUrl } from './utils.js';

function Avatar({ person, size }) {
  return (
    <img
      className="avatar"
      src={getImageUrl(person)}
      alt={person.name}
      width={size}
      height={size}
    />
  );
}

export default function Profile() {
  return (
    <div>
      <Avatar
        size={100}
        person={{ 
          name: 'Katsuko Saruhashi', 
          imageId: 'YfeOqp2'
        }}
      />
      <Avatar
        size={80}
        person={{
          name: 'Aklilu Lemma', 
          imageId: 'OKS67lh'
        }}
      />
      <Avatar
        size={50}
        person={{ 
          name: 'Lin Lanying',
          imageId: '1bX5QH6'
        }}
      />
    </div>
  );
}

Props ເຮັດໃຫ້ທ່ານຄິດກ່ຽວກັບ parent ແລະ child component ຢ່າງອິດສະຫຼະ. ຕົວຢ່າງ, ທ່ານສາມາດປ່ຽນ prop person ຫຼື size ພາຍໃນ Profile ໂດຍບໍ່ຈຳເປັນຕ້ອງຄິດວ່າ Avatar ໃຊ້ສິ່ງນີ້ແນວໃດ. ຄ້າຍຄືກັນ, ທ່ານສາມາດປ່ຽນວິທີທີ່ Avatar ໃຊ້ props, ໂດຍບໍ່ຕ້ອງເບິ່ງທີ່ Profile.

ທ່ານສາມາດຄິດວ່າ props ຄືກັບລູກບິດທີ່ທ່ານສາມາດປັບໄດ້. ມັນເຮັດໜ້າທີ່ເປັນ argument ທີ່ເຮັດວຽກສຳລັບຟັງຊັ່ນ-ຄວາມຈິງ, props ເປັນ argument ດຽວສຳລັບ component ຂອງທ່ານ! ຟັງຊັ່ນ component React ຮັບ argument ດຽວ, props object:

function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
}

ປົກະຕິແລ້ວທ່ານບໍ່ຈຳເປັນຕ້ອງໃຊ້ props object ທັງໝົດ, ສະນັ້ນ ທ່ານສາມາດແຕກມັນອອກເປັນ props ຍ່ອຍແຕ່ລະອັນ.

Pitfall

ຢ່າລືມວົງປີກກາ { ແລະ } ພາຍໃນຂອງ ( ແລະ ) ເມື່ອປະກາດ props:

function Avatar({ person, size }) {
// ...
}

Syntax ເອີ້ນວ່າ “destructuring” ແລະ ເທົ່າກັນກັບການອ່ານຄ່າ propertie ຈາກ function parameter:

function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
}

ການລະບຸຄ່າເລີ່ມຕົ້ນສຳລັບ prop

ຫາກທ່ານຕ້ອງການໃຫ້ຄ່າ prop ເລີ່ມຕົ້ນເພື່ອໃຊ້ແທນເມື່ອບໍ່ໄດ້ລະບຸຄ່າໄວ້, ທ່ານສາມາດເຮັດໄດ້ໂດຍການ destructuring ໂດຍໃສ່ = ແລະ ຄ່າເລີ່ມຕົ້ນໄວ້ຫຼັງ parameter:

function Avatar({ person, size = 100 }) {
// ...
}

ຕອນນີ້, ຖ້າ <Avatar person={...} /> ສະແດງໂດຍບໍ່ມີ prop size, size ຈະຖືກຕັ້ງຄ່າເປັນ 100.

ຄ່າເລີ່ມຕົ້ນຈະຖືກໃຊ້ກໍຕໍ່ເມືອບໍ່ມີ prop size ຫຼື ຖ້າທ່ານສົ່ງ size={undefined}. ແຕ່ຖ້າທ່ານສົ່ງ size={null} ຫຼື size={0}, ຄ່າເລີ່ມຕົ້ນຈະ ບໍ່ຖືກ ໃຊ້.

ການສົ່ງຕໍ່ props ດ້ວຍ spread syntax JSX

ບາງເທື່ອ, ການສົ່ງ props ແມ່ນຊໍ້າກັນຫຼາຍ:

function Profile({ person, size, isSepia, thickBorder }) {
return (
<div className="card">
<Avatar
person={person}
size={size}
isSepia={isSepia}
thickBorder={thickBorder}
/>
</div>
);
}

ມັນບໍ່ມີຫຍັງຜິດຖ້າ code ຊໍ້າ-ມັນສາມາດອ່ານໄດ້ຊັດເຈນຂຶ້ນ. ແຕ່ບາງຄັ້ງທ່ານອາດໃຫ້ຄວາມສຳຄັນກັບຄວາມກະທັດຮັດ. ບາງ component ສົ່ງຜ່ານ props ທັງໝົດໄປຫາ children ຂອງມັນທັງໝົດ, ເຊັ່ນດຽວກັບວິທີ Profile ນີ້ເຮັດກັບ Avatar. ເພາະວ່າພວກມັນບໍ່ໃຊ້ prop ໂດຍກົງ, ຈຶ່ງເໝາະສົມທີ່ຈະໃຊ້ syntax “spread” ທີກະທັດຮັດກວ່ານີ້:

function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
</div>
);
}

ນີ້ສົ່ງຕໍ່ prop ທັງໝົດຂອງ Profile ໄປຫາ Avatar ໂດຍບໍ່ລະບຸຊື່ແຕ່ລະລາຍການ.

ໃຊ້ spread syntax ດ້ວຍຄວາມລະມັດລະວັງ. ຖ້າທ່ານໃຊ້ມັນທຸກໆ component ອື່ນ, ສະແດງວ່າມີບາງຢ່າງຜິດປົກະຕິ. ສ່ວນຫຼາຍ, ມັນບົ່ງບອກວ່າທ່ານຄວນຈະແຍກ component ແລະ ສົ່ງ children ເປັນ JSX. ເພີ່ມເຕີມຕໍ່ໄປ!

ການສົ່ງ JSX ເປັນ children

ມັນເປັນເລື່ອງປົກະຕິທີ່ຈະຊ້ອນ built-in ແທັກບາວເຊີ:

<div>
<img />
</div>

ບາງເທື່ອທ່ານຕ້ອງການຊ້ອນ component ຂອງທ່ານດ້ວຍຮູບແບບດຽວກັນ:

<Card>
<Avatar />
</Card>

ເມື່ອທ່ານຊ້ອນເນື້ອຫາພາຍໃນແທັກ JSX, parent component ຈະຮັບເນື້ອຫາໃນ prop ເອີ້ນວ່າ children. ຕົວຢ່າງ, component Card ດ້ານລຸ່ມຈະຮັບ prop children ຕັ້ງຄ່າໃຫ້ <Avatar /> ແລະ ສະແດງຜົນທາງໃນ div ທີ່ຄອບ:

import Avatar from './Avatar.js';

function Card({ children }) {
  return (
    <div className="card">
      {children}
    </div>
  );
}

export default function Profile() {
  return (
    <Card>
      <Avatar
        size={100}
        person={{ 
          name: 'Katsuko Saruhashi',
          imageId: 'YfeOqp2'
        }}
      />
    </Card>
  );
}

ລອງແທນທີ່ <Avatar> ພາຍໃນ <Card> ດ້ວຍຂໍ້ຄວາມເພື່ອເບິ່ງວ່າ component Card ສາມາດຄອບເນື້ອຫາທີ່ຊ້ອນກັນ. ມັນບໍ່ຈຳເປັນຕ້ອງ “ຮູ້” ສິ່ງທີ່ກຳລັງສະແດງພາຍໃນມັນ. ທ່ານຈະເຫັນຮູບແບບທີ່ຢືດຫຍຸ່ນນີ້ຫຼາຍບ່ອນ.

ທ່ານສາມາດຄິດວ່າ component ທີ່ມີ prop children ວ່າມີ “ຂຸມ” ທີ່ສາມາດ “ເຕິມລົງ” ໂດຍ parent component ດ້ວຍ JSX ຕາມໃຈ. ທ່ານຈະໄດ້ໃຊ້ prop children ເລື້ອຍໆສຳລັບການຫໍ່ຫຸ້ມພາບເຊັ່ນ: panels, grids, ແລະ ອື່ນໆ.

A puzzle-like Card tile with a slot for "children" pieces like text and Avatar

Illustrated by Rachel Lee Nabors

props ປ່ຽນແປງແນວໃດເມື່ອເວລາຜ່ານໄປ

Component Clock ດ້ານລຸ່ມຈະໄດ້ຮັບສອງ prop ຈາກ parent component ມັນເອງ: color ແລະ time. (Code ຂອງ parent component ແມ່ນຖືກປະໄວ້ເພາະວ່າມັນໃຊ້state, ທີ່ພວກເຮົາຍັງບໍ່ທັນເຈາະລົງເລິກໄປຕື່ມເທື່ອ.)

ລອງປ່ຽນສີໃນ select box ດ້ານລຸ່ມ:

export default function Clock({ color, time }) {
  return (
    <h1 style={{ color: color }}>
      {time}
    </h1>
  );
}

ໃນຕົວຢ່າງນີ້ສະແດງໃຫ້ເຫັນວ່າ component ອາດໄດ້ຮັບ prop ທີ່ແຕກຕ່າງເມື່ອເວລາຜ່ານໄປ. Props ບໍ່ເປັນ static ສະເໝີໄປ! ນີ້, prop time ປ່ຽນແປງທຸກວິນາທີ, ແລະ prop color ປ່ຽນເມື່ອທ່ານເລືອກສີອື່ນ. Prop ສະທ້ອນຂໍ້ມູນ component ໃນເວລາໃດໜຶ່ງ, ແທນທີ່ຈະສະແດງສະເພາະໃນຊ່ວງເລີ່ມຕົ້ນ.

ເຖິງຢ່າງໃດກໍຕາມ, props ແມ່ນ immutable—ຄຳສັບຈາກວິທະຍາສາດຄອມພິວເຕີມີຄວາມໝາຍວ່າ “ບໍ່ປ່ຽນແປງ”. ເມື່ອ component ຕ້ອງການປ່ຽນແປງ prop ມັນເອງ (ຍົກຕົວຢ່າງ, ໃນຕອນ response ຫາການໂຕ້ຕອບຜູ້ໃຊ້ ຫຼື ຂໍ້ມູນໃໝ່), ມັນຕ້ອງໄດ້ “ຂໍ” parent component ຂອງມັນເອງເພື່ອສົ່ງ prop ທີ່ແຕກຕ່າງ—object ໃໝ່! prop ເກົ່າຈະຖືກຖີ້ມ ແລະ ໃນທີ່ສຸດ JavaScript engine ຈະເອີ້ນຄືນ memory ທີ່ພວກມັນເອົາໄປ.

ຢ່າພາຍາຍາມ “ປ່ຽນ props”. ເມື່ອທ່ານຕ້ອງການ respond ຄືນຫາ user input (ເຊັ່ນ ປ່ຽນສີທີ່ເລືອກ), ທ່ານຈະຕ້ອງການ “set state”, ທີ່ທ່ານໄດ້ຮຽນກ່ຽວກັບ State: A Component’s Memory.

Recap

  • ຫາກຕ້ອງການສົ່ງ props, ໃຫ້ເພີ່ມລົງໃນ JSX, ເຊັ່ນດຽວກັບທີ່ທ່ານເຮັດກັບ attribute HTML.
  • ຫາກຕ້ອງການອ່ານ props, ໃຊ້ destructuring syntax function Avatar({ person, size}).
  • ທ່ານສາມາດກຳນົດຄ່າເລີ່ມຕົ້ນເຊັ່ນ size = 100, ເຊິ່ງໃຊ້ສຳລັບ props ທີ່ບໍ່ມີ ຫຼື ເປັນ undefined.
  • ທ່ານສາມາດສົ່ງຕໍ່ທຸກ props ດ້ວຍ JSX spread syntax <Avatar {...props} />, ແຕ່ຢ່າໃຊ້ມັນຫຼາຍ!
  • JSX ທີ່ຊ້ອນກັນຫຼາຍເຊັ່ນ <Card><Avatar /></Card> ຈະປະກົດເປັນ children component ຂອງ component Card.
  • Props ແມ່ນ snapshot ທີ່ອ່ານໄດ້ຢ່າງດຽວໃນເວລາ: ທຸກໆການສະແດງຜົນຈະຮັບເວີຊັ່ນໃໝ່ຂອງ props.
  • ທ່ານບໍ່ສາມາດປ່ຽນ props. ເມື່ອທ່ານຕ້ອງການ ການໂຕ້ຕອບ, ທ່ານຈະຕ້ອງຕັ້ງຄ່າ state.

Challenge 1 of 3:
ແຕກ component

Component Gallery ນີ້ມີ markup ທີ່ຄ້າຍກັນຫຼາຍສຳລັບສອງ profile. ແຕກ component Profile ອອກມາເພື່ອຫຼຸດຄວາມຊໍ້າຊ້ອນ. ທ່ານຕ້ອງເລືອກ prop ທີ່ຈະສົ່ງໄປຫາມັນ.

import { getImageUrl } from './utils.js';

export default function Gallery() {
  return (
    <div>
      <h1>Notable Scientists</h1>
      <section className="profile">
        <h2>Maria Skłodowska-Curie</h2>
        <img
          className="avatar"
          src={getImageUrl('szV5sdG')}
          alt="Maria Skłodowska-Curie"
          width={70}
          height={70}
        />
        <ul>
          <li>
            <b>Profession: </b> 
            physicist and chemist
          </li>
          <li>
            <b>Awards: 4 </b> 
            (Nobel Prize in Physics, Nobel Prize in Chemistry, Davy Medal, Matteucci Medal)
          </li>
          <li>
            <b>Discovered: </b>
            polonium (element)
          </li>
        </ul>
      </section>
      <section className="profile">
        <h2>Katsuko Saruhashi</h2>
        <img
          className="avatar"
          src={getImageUrl('YfeOqp2')}
          alt="Katsuko Saruhashi"
          width={70}
          height={70}
        />
        <ul>
          <li>
            <b>Profession: </b> 
            geochemist
          </li>
          <li>
            <b>Awards: 2 </b> 
            (Miyake Prize for geochemistry, Tanaka Prize)
          </li>
          <li>
            <b>Discovered: </b>
            a method for measuring carbon dioxide in seawater
          </li>
        </ul>
      </section>
    </div>
  );
}