העברת אביזרים לרכיב

React רכיבים use props כדי לתקשר אחד עם השני. כל רכיב אב יכול להעביר מידע מסוים לרכיבי הצאצא שלו על ידי מתן props. אביזרים עשויים להזכיר לך את תכונות HTML, אבל אתה יכול להעביר דרכם כל ערך JavaScript, כולל אובייקטים, מערכים ופונקציות.

You will learn

  • איך להעביר את props לרכיב
  • איך לקרוא props מתוך רכיב
  • כיצד לציין ערכי ברירת מחדל עבור props
  • איך להעביר כמה JSX לרכיב
  • איך 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 תואם לתקן HTML). אבל אתה יכול להעביר כל props לרכיבים שלכם, כמו <Avatar>, כדי להתאים אותם. הנה איך להתאים אותם!

העברת props לרכיב

בקוד זה, הרכיב Profile אינו מעביר שום props לרכיב הצאצא שלו, Avatar:

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

אתה יכול לתת ל-Avatar כמה props בשני שלבים.

שלב 1: העבר props לרכיב הצאצא

ראשית, העבירו כמה props ל-Avatar. לדוגמה, בוא נעביר שניים props: person (אובייקט), ו-size (מספר):

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

Note

אם סוגרים כפולים מתולתלים אחרי person= confuse אותך, זכור הם רק אובייקט בתוך ה-JSX.

עכשיו אתה יכול לקרוא את props אלה בתוך רכיב Avatar.

שלב 2: קרא את props בתוך רכיב הילד

אתה יכול לקרוא את props אלה על ידי רישום שמותיהם person, size מופרדים בפסיקים בתוך ({ ו}) ישירות אחרי function Avatar. זה מאפשר לך use אותם בתוך קוד Avatar, כמו שהיית עושה עם משתנה.

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

הוסף קצת היגיון לAvatar שuse הוא person וsize props לעיבוד, וסיימתם.

כעת אתה יכול להגדיר את Avatar לעיבוד בדרכים רבות ושונות עם props שונה. נסה לשנות את הערכים!

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

אביזרים מאפשרים לך לחשוב על מרכיבי הורה וילד באופן עצמאי. לדוגמה, אתה יכול לשנות את ה-person או את ה-size props בתוך Profile מבלי שתצטרך לחשוב איך Avatar use מפעיל אותם. באופן דומה, אתה יכול לשנות את האופן שבו Avatar use הם props, מבלי להסתכל על Profile.

אתה יכול לחשוב על props כמו “כפתורים” שאתה יכול להתאים. הם משרתים את אותו תפקיד שבו ארגומנטים משמשים עבור פונקציות - למעשה, props הם הארגומנט היחיד לרכיב שלך! פונקציות רכיב React מקבלים ארגומנט בודד, אובייקט props:

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

בדרך כלל אתה לא צריך את כל האובייקט props עצמו, אז אתה מפרק אותו ל-props בודד.

Pitfall

אל תפספסו את צמד התלתלים { ו} בתוך ( ו) בעת הצהרה על props:

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

תחביר זה נקרא “destructuring” והוא שווה ערך לקריאת מאפיינים מפרמטר פונקציה:

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

ציון ערך ברירת מחדל עבור אבזר

אם אתה רוצה לתת לפרופס ערך ברירת מחדל לחזור עליו כאשר לא צוין ערך, אתה יכול לעשות זאת עם הרס על ידי הצבת = וערך ברירת המחדל מיד אחרי הפרמטר:

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

כעת, אם <Avatar person={...} /> מוצג ללא אבזר size, ה-size יוגדר ל-100.

ערך ברירת המחדל הוא used בלבד אם האביזר size חסר או אם עוברים את size={undefined}. אבל אם תעבור את size={null} או size={0}, ערך ברירת המחדל יהיה לא used.

העברת props עם תחביר התפשטות JSX

לפעמים, מעבר props חוזר על עצמו מאוד:

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

אין שום דבר רע בקוד שחוזר על עצמו - הוא יכול להיות קריא יותר. אבל לפעמים אתה עשוי להעריך תמציתיות. חלק מהרכיבים מעבירים את כל ה-props שלהם לילדים שלהם, כמו איך שה-Profile הזה עושה עם Avatar. בגלל use הם לא use שום props שלהם ישירות, זה יכול להיות הגיוני use תחביר “מפוזר” תמציתי יותר:

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

זה מעביר את כל ה-props של Profile ל-Avatar מבלי לרשום כל אחד מהשמות שלהם.

השתמש בתחביר התפשטות עם איפוק. אם אתה משתמש בו בכל רכיב אחר, משהו לא בסדר. לעתים קרובות, זה מציין שאתה צריך לפצל את הרכיבים שלך ולהעביר ילדים בתור JSX. עוד על כך בהמשך!

עוברים JSX בתור ילדים

מקובל לקנן תגיות דפדפן מובנות:

<div>
<img />
</div>

לפעמים תרצה לקנן את הרכיבים שלך באותו אופן:

<Card>
<Avatar />
</Card>

כאשר אתה מקנן תוכן בתוך תג JSX, רכיב האב יקבל את התוכן הזה באביזר שנקרא children. לדוגמה, הרכיב Card להלן יקבל אבזר children שנקבע ל-<Avatar /> ויעבד אותו ב-diver wrapper:

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> בטקסט כלשהו כדי לראות כיצד הרכיב Card יכול לעטוף כל תוכן מקונן. זה לא צריך “לדעת” מה מוצג בתוכו. אתה תראה את הדפוס הגמיש הזה במקומות רבים.

אתה יכול לחשוב על רכיב עם אבזר children כבעל “חור” שניתן “למלא” על ידי רכיבי האב שלו עם JSX שרירותי. לעתים קרובות אתה use אביזר children עבור עטיפות חזותיות: לוחות, רשתות וכו’.

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

Illustrated by Rachel Lee Nabors

איך props משתנה עם הזמן

הרכיב Clock למטה מקבל שני props מהרכיב האב שלו: color ו-time. (קוד רכיב האב מושמט בגלל uses state, שעדיין לא נצלול אליו.)

נסה לשנות את הצבע בתיבת הבחירה למטה:

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

דוגמה זו ממחישה כי רכיב עשוי לקבל props שונה לאורך זמן. האביזרים אינם תמיד סטטיים! כאן, אביזר time משתנה כל שנייה, ואביזר color משתנה כאשר אתה בוחר צבע אחר. אביזרים משקפים נתונים של רכיב בכל נקודת זמן, ולא רק בהתחלה.

עם זאת, props הם בלתי ניתנים לשינוי—a מונח ממדעי המחשב שפירושו “בלתי ניתן לשינוי”. כאשר רכיב צריך לשנות את props שלו (לדוגמה, בתגובה לאינטראקציה user או נתונים חדשים), הוא יצטרך “לבקש” מהרכיב האב שלו להעביר אותו K_4 אובייקט ישן!___ לאחר מכן props יושלך הצידה, ובסופו של דבר מנוע JavaScript ידרוש בחזרה את memory שנלקח על ידם.

אל תנסה “לשנות את props”. כאשר אתה צריך להגיב לקלט user (כמו שינוי הצבע שנבחר), תצטרך “להגדיר state”, עליו תוכל ללמוד ב-State: A Component’s Memory.ry

Recap

  • כדי לעבור את props, הוסף אותם ל-JSX, בדיוק כמו שהיית עושה עם תכונות HTML.
  • כדי לקרוא את props, use את תחביר ההסרה של function Avatar({ person, size }).
  • אתה יכול לציין ערך ברירת מחדל כמו size = 100, שהוא used עבור חסר וundefined props.
  • אתה יכול להעביר את כל props עם <Avatar {...props} /> JSX התחביר התפשט, אבל אל תגזים עםuse!
  • JSX מקונן כמו <Card><Avatar /></Card> יופיע בתור רכיב children של רכיב Card.
  • אביזרים הם צילומי מצב לקריאה בלבד בזמן: כל עיבוד מקבל גרסה חדשה של props.
  • אתה לא יכול לשנות את props. כאשר אתה צריך אינטראקטיביות, תצטרך להגדיר state.

Challenge 1 of 3:
חלץ רכיב

רכיב Gallery זה מכיל סימון דומה מאוד עבור שני פרופילים. חלץ ממנו רכיב Profile כדי להפחית את הכפילות. תצטרך לבחור איזה props להעביר אליו.

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 (chemical 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>
  );
}