רשימות עיבוד

לעתים קרובות תרצה להציג מספר רכיבים דומים מאוסף נתונים. אתה יכול use את JavaScript שיטות מערך כדי לתפעל מערך של נתונים. בדף זה, תבצע use filter() ו-map() עם https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map) עם https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map) עם https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map) עם React של רכיבי נתונים של מערך הנתונים שלך ויבצע סינון של מערך נתונים.

You will learn

  • כיצד לעבד רכיבים ממערך באמצעות map() של JavaScript
  • כיצד לעבד רק רכיבים ספציפיים באמצעות filter() של JavaScript
  • מתי ומדוע use React מפתחות

עיבוד נתונים ממערכים

אמור שיש לך רשימה של תוכן.

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

ההבדל היחיד בין אותם פריטי רשימה הוא התוכן שלהם, הנתונים שלהם. לעתים קרובות תצטרך להציג מספר מופעים של אותו רכיב באמצעות נתונים שונים בעת בניית ממשקים: מרשימות של הערות ועד גלריות של תמונות פרופיל. במצבים אלה, אתה יכול לאחסן את הנתונים האלה באובייקטים ומערכים JavaScript ובשיטות use כמו map() ו-filter() כדי להציג רשימות של רכיבים מהם.

להלן דוגמה קצרה כיצד ליצור רשימה של פריטים ממערך:

  1. העבר את הנתונים למערך:
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. מפה את חברי people למערך חדש של צמתים JSX, listItems:
const listItems = people.map(person => <li>{person}</li>);
  1. החזר listItems מהרכיב שלך עטוף ב-<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>;
}

שימו לב שארגז החול שלמעלה מציג שגיאת מסוף:

Console
אזהרה: לכל ילד ברשימה צריך להיות אביזר “מפתח” ייחודי.

תלמד כיצד לתקן שגיאה זו בהמשך דף זה. לפני שנגיע לזה, בואו נוסיף קצת מבנה לנתונים שלכם.

סינון מערכי פריטים

ניתן לבנות את הנתונים הללו אפילו יותר.

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'. אתה יכול use JavaScript של filter() להחזיר רק את האנשים האלה. שיטה זו לוקחת מערך של פריטים, מעבירה אותם דרך “מבחן” (פונקציה שמחזירה true או false), ומחזירה מערך חדש של רק אותם פריטים שעברו את המבחן (החזירו true).

אתה רוצה רק את הפריטים שבהם profession הוא 'chemist'. הפונקציה “בדיקה” עבור זה נראית כמו (person) => person.profession === 'chemist'. הנה איך להרכיב את זה:

  1. צור מערך חדש של אנשים “כימאים” בלבד, chemists, על ידי קריאה ל-filter() ב-people סינון לפי person.profession === 'chemist':
const chemists = people.filter(person =>
person.profession === 'chemist'
);
  1. כעת מפה מעל 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. לבסוף, החזר את ה-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 === '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

פונקציות חץ מחזירות באופן מרומז את הביטוי מיד אחרי =>, כך שלא היית צריך return statement:

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

עם זאת, עליך לכתוב return במפורש אם => שלך מלווה בפלטה מתולתלת {!

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

אומרים שפונקציות חץ המכילות => { בעלות “גוף חסום”. הן מאפשרות לך לכתוב יותר משורת קוד בודדת, אבל אתה חייב לכתוב return statement בעצמך. אם תשכח אותו, שום דבר לא יוחזר!

שמירה על סדר פריטי רשימה עם key

שימו לב שכל ארגזי החול שלמעלה מציגים שגיאה במסוף:

Console
אזהרה: לכל ילד ברשימה צריך להיות אביזר “מפתח” ייחודי.

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

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

Note

אלמנטים JSX ישירות בתוך שיחת map() תמיד צריכים מפתחות!

מקשים אומרים React לאיזה פריט מערך כל רכיב מתאים, כך שהוא יוכל להתאים אותם מאוחר יותר. זה הופך להיות חשוב אם פריטי המערך שלך יכולים לזוז (למשל עקב מיון), להכנס או להימחק. key שנבחר היטב עוזר לReact להסיק מה בדיוק קרה, ולבצע את העדכונים הנכונים לעץ DOM.

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

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 עבור כל פריט רשימה

מה אתה עושה כאשר כל פריט צריך לרנדר לא אחד, אלא כמה צמתים DOM?

התחביר הקצר <>...</> Fragment לא יאפשר לך להעביר מפתח, אז אתה צריך לקבץ אותם ל-<div> בודד, או use את התחביר <Fragment> המפורש יותר:](/__reference_TK/reference/referenceK/reference/referenceK/reference)

import { Fragment } from 'react';

// ...

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

Fragments נעלמים מה-DOM, אז זה ייצור רשימה שטוחה של <h1>, <p>, <h1>, <p>, וכן הלאה.

היכן ניתן להשיג את key שלך

מקורות נתונים שונים מספקים מקורות מפתח שונים:

  • נתונים ממסד נתונים: אם הנתונים שלך מגיעים ממסד נתונים, אתה יכול use את מפתחות/מזהי מסד הנתונים, שהם ייחודיים מטבעם.
  • נתונים שנוצרו באופן מקומי: אם הנתונים שלך נוצרים ונמשכים באופן מקומי (למשל הערות באפליקציה לרישום הערות), use מונה גדל, crypto.randomUUID() או חבילה כמו uuid בעת יצירת פריטים.

כללי המפתחות

  • מפתחות חייבים להיות ייחודיים בין אחים. עם זאת, זה בסדר use אותם מפתחות עבור צמתים JSX ב-מערכים שונים.
  • ** אסור לשנות את המפתחות** או שזה מביס את מטרתם! אל תיצור אותם בזמן העיבוד.

למה React צריך מפתחות?

תאר לעצמך שלקבצים בשולחן העבודה שלך לא היו שמות. במקום זאת, תתייחס אליהם לפי הסדר שלהם — הקובץ הראשון, הקובץ השני וכן הלאה. אתה יכול לקבל used אליו, אבל ברגע שתמחק קובץ, זה היה מבלבל. הקובץ השני יהפוך לקובץ הראשון, הקובץ השלישי יהיה הקובץ השני וכן הלאה.

שמות קבצים בתיקייה ומפתחות JSX במערך משרתים מטרה דומה. הם מאפשרים לנו לזהות באופן ייחודי פריט בין אחיו. מפתח שנבחר היטב מספק מידע רב יותר מהמיקום בתוך המערך. גם אם ה_מיקום_ משתנה עקב הזמנה מחדש, ה-key מאפשר לReact לזהות את הפריט לאורך כל חייו.

Pitfall

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

באופן דומה, אל תיצור מפתחות תוך כדי תנועה, למשל. עם key={Math.random()}. זה יגרום למפתחות use לעולם לא להתאים בין עיבודים, מה שיוביל לכך שכל הרכיבים שלך וDOM ייצרו מחדש בכל פעם. לא רק שזה איטי, אלא שהוא גם יאבד כל קלט user בתוך פריטי הרשימה. במקום זאת, use מזהה יציב המבוסס על הנתונים.

שים לב שהרכיבים שלך לא יקבלו key כאביזר. זה רק used כרמז על ידי React עצמו. אם הרכיב שלך צריך מזהה, עליך להעביר אותו כאביזר נפרד: <Profile key={id} userId={id} />.

Recap

בעמוד זה למדת:

  • איך להעביר נתונים מתוך רכיבים לתוך מבני נתונים כמו מערכים ואובייקטים.
  • כיצד ליצור סטים של רכיבים דומים עם ה-map() של JavaScript.
  • כיצד ליצור מערכים של פריטים מסוננים עם filter() של JavaScript.
  • למה ואיך להגדיר key על כל רכיב באוסף כדי שReact יוכל לעקוב אחר כל אחד מהם גם אם המיקום או הנתונים שלו משתנים.

Challenge 1 of 4:
פיצול רשימה לשניים

דוגמה זו מציגה רשימה של כל האנשים.

שנה אותו כדי להציג שתי רשימות נפרדות בזו אחר זו: כימאים וכל השאר. כמו בעבר, תוכל לקבוע אם אדם הוא כימאי על ידי בדיקה אם 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>
  );
}