קומפוננטות ו-Props
קומפוננטות מאפשרות לכם לפצל את ממשק המשתמש לחתיכות עצמאיות המאפשרות שימוש חוזר, ולחשוב על כל חתיכה בנפרד. דף זה מספק מבוא לרעיון של קומפוננטות. תוכלו למצוא הסבר מפורט של ה-API של קומפוננטות כאן.
מבחינה תפיסתית, קומפוננטות הן כמו פונקציות JavaScript. הן מקבלות קלט שרירותי (נקרא “props”) ומחזירות אלמנטים של React המתארים מה אמור להופיע על המסך.
קומפוננטות מסוגי פונקציות ומחלקות
הדרך הפשוטה ביותר להגדיר קומפוננטה היא לכתוב פונקציית JavaScript:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
פונקציה זו היא קומפוננטת React חוקית משום שהיא מקבלת ארגומנט אובייקט נתונים יחיד מסוג “props” (קיצור של המילה תכונות, properties באנגלית) ומחזירה אלמנט React. אנו מכנים קומפוננטות כאלה “קומפוננטת פונקציה” משום שהם פשוט פונקציות JavaScript.
תוכלו גם להשתמש במחלקה של ES6 כדי להגדיר קומפוננטה:
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
שתי הקומפוננטות מעלה הן זהות מנקודת המבט של React.
לקומפוננטות פונקציה ומחלקות יש כמה פיצ’רים נוספים שנדבר עליהם בקטעים הבאים.
רינדור של קומפוננטה
עד כה, נתקלנו רק ברכיבי React שמייצגים תגי DOM:
const element = <div />;
עם זאת, אלמנטים יכולים גם לייצג קומפוננטות המוגדרות על ידי המשתמש:
const element = <Welcome name="Sara" />;
כאשר React רואה אלמנט המייצג קומפוננטה שהודגרה על ידי המשתמש, היא מעבירה את המאפיינים שהוגדרו ב-JSX ואת ה”ילדים” לקומפוננטה זו כאובייקט יחיד. אנו קוראים לאובייקט זה “props”.
לדוגמה, הקוד הזה מרנדר “Hello, Sara” על העמוד:
function Welcome(props) { return <h1>Hello, {props.name}</h1>;
}
const root = ReactDOM.createRoot(document.getElementById('root'));
const element = <Welcome name="Sara" />;root.render(element);
בואו נסכם מה קורה בדוגמה זו:
<<<<<<< HEAD
- אנחנו קוראים ל-
ReactDOM.render()
עם האלמנט<Welcome name="Sara" />
. - React קוראת לקומפוננטת
Welcome
עם{name: 'Sara'}
בתור ה-props. - קומפוננטת
Welcome
שלנו מחזירה אלמנט<h1>Hello, Sara</h1>
בתור התוצאה שלה. -
React DOM מעדכן ביעילות את ה-DOM להיות תואם ל-
<h1>Hello, Sara</h1>
. - We call
root.render()
with the<Welcome name="Sara" />
element. - React calls the
Welcome
component with{name: 'Sara'}
as the props. - Our
Welcome
component returns a<h1>Hello, Sara</h1>
element as the result. -
React DOM efficiently updates the DOM to match
<h1>Hello, Sara</h1>
.84ad3308338e2bb819f4f24fa8e9dfeeffaa970b
הערה: יש להתחיל שמות קומפוננטות עם אות גדולה.
React מתייחסת לקומפוננטות המתחילות באותיות קטנות בתור תגי DOM. לדוגמה,
<div />
מייצג תג div של HTML, אך<Welcome />
מייצג קומפוננטה ומחייב אתWelcome
להיות ב-scope.כדי ללמוד עוד על הסיבות מאחורי קונבנציה זו, אנא קראו את JSX באופן מעמיק.
יצירת קומפוננטות
קומפוננטות יכולות להתייחס לקומפוננטות אחרות בפלט שלהם. דבר זה מאפשר לנו להשתמש באותה הפשטת קומפוננטות עבור כל רמה של פירוט. לחצן, טופס, תיבת דו-שיח, מסך: באפליקציות React, כל אלה בדרך כלל באים לידי ביטוי כקומפוננטות.
למשל, אנו יכולים ליצור קומפוננטת App
שמרנדרת את Welcome
הרבה פעמים:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" /> <Welcome name="Cahal" /> <Welcome name="Edite" /> </div>
);
}
בדרך כלל, אפליקציות React חדשות כוללות קומפוננטת App
אחת בראש האפליקציה. עם זאת, אם תשלבו את React באפליקציה קיימת, תוכלו להתחיל מלמטה למעלה באמצעות קומפוננטה קטנה כגון Button
, ובהדרגה להגיע לחלק העליון ביותר של הירארכיית התצוגה.
חילוץ קומפוננטות
אל תפחדו לפצל קומפוננטות לקומפוננטות קטנות יותר.
למשל, הביטו בקומפוננטת Comment
הבאה:
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
היא מקבלת את author
(אובייקט), text
(מחרוזת) ו-date
(תאריך) בתור props, ומתארת תגובה באתר אינטרנט של מדיה חברתית.
קומפוננטה זו יכולה להיות מסובכת לשינוי בגלל כל הקינון שבה, ובנוסף קשה לעשות שימוש חוזר בחלקים אינדיבידואלים שלה. בואו נחלץ מספר קומפוננטות ממנה.
ראשית, נחלץ את Avatar
:
function Avatar(props) {
return (
<img className="Avatar" src={props.user.avatarUrl} alt={props.user.name} /> );
}
ה-Avatar
לא צריך לדעת שהוא מתרנדר בתוך Comment
. זו הסיבה שבגללה נתנו ל-prop שלו שם גנרי יותר: user
(משתמש) ולא author
(מחבר).
אנו ממליצים על מתן שמות ל-props מנקודת המבט של הקומפוננטה עצמה ולא על סמך הקונטקסט שבו הם נמצאים בשימוש.
אנו יכולים כעת לפשט Comment
מעט:
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<Avatar user={props.author} /> <div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
בשלב הבא, נחלץ את קומפוננטת UserInfo
שמרנדרת Avatar
לצד שם המשתמש:
function UserInfo(props) {
return (
<div className="UserInfo"> <Avatar user={props.user} /> <div className="UserInfo-name"> {props.user.name} </div> </div> );
}
זה מאפשר לנו לפשט את Comment
אפילו יותר:
function Comment(props) {
return (
<div className="Comment">
<UserInfo user={props.author} /> <div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
חילוץ קומפוננטות אולי נראה כמו עבודה שחורה בהתחלה, אבל בעלות על מגוון קומפוננטות לשימוש חוזר משתלמת באפליקציות גדולות יותר. כלל אצבע טוב הוא שאם חלק מממשק המשתמש שלכם נמצא בשימוש מספר פעמים (Button
, Panel
, Avatar
), או שהוא מורכב מספיק בכוחות עצמו (App
, FeedStory
, Comment
), הוא מועמד טוב להיות מחולץ לקומפוננטה אחרת.
Props הם לקריאה בלבד
בין אם אתם מצהירים על קומפוננטה כפונקציה או כמחלקה, אסור לה לעולם לשנות את ה-props שלה. הביטו בפונקציה sum
הבאה:
function sum(a, b) {
return a + b;
}
פונקציות אלה נקראות “טהורות” מכיוון שהן לא מנסות לשנות את הקלטים שלהן, ותמיד מחזירות את אותה התוצאה עבור אותם קלטים.
לעומת זאת, פונקציה זו אינה טהורה משום שהיא משנה את הקלט שלה:
function withdraw(account, amount) {
account.total -= amount;
}
React היא די גמישה אבל יש לה כלל אחד נוקשה:
כל קומפוננטות React חייבות לפעול כמו פונקציות טהורות ביחס ל-props שלהן.
כמובן, ממשקי המשתמש של אפליקציות הם דינמיים ומשתנים עם הזמן. בחלק הבא, נציג את הקונספט החדש של “state” (מצב). ה-state מאפשר לקומפוננטות React לשנות את הפלט שלהן לאורך הזמן בתגובה לפעולות משתמש, תשובות מהרשת, וכל דבר אחר, מבלי להפר כלל זה.