ריאקט – קומפוננטות עם סטייטים

לנהל את הקומפוננטה שלנו באמצעות סטייטים. לא עוד קומפוננטות סטטיות!

במאמרים הקודמים למדנו על קומפוננטות. אבל מה הבעיה עם הקומפוננטות האלו? הן די פשוטות ומשמשות להצגת תוכן בלבד בעוד שרוב הקומפוננטות שנרצה ליצור מחייבות איזושהי אינטראקציה וחייבות לאכסן בתוכן איזשהו מידע שמשתנה. המידע יכול להגיע מבחוץ, יכול להגיע מבפנים או מכל מקום אחר, אבל הקומפוננטה חייבת להכיל מידע ולאכסן אותו. זה נקרא state. כאשר קומפוננטות פשוטות המשמשות לתצוגה בלבד נקראות stateless וקומפוננטות שצריכות לשמור בתוכן מידע הן קומפוננטות שמחייבות state. מבהיל? לא ממש. אם אתם יודעים לעבוד עם תכונות, ולמדנו את זה באחד המאמרים הקודמים, תדעו להסתדר עם state. בגדול, מדובר באובייקט שמכיל מידע ואת המידע הזה אפשר לשנות.

בואו ונדגים, הכל יותר פשוט עם דוגמה. נניח ואתם עובדים בחברת פח לשיווק מוצר סייברי כושל. למשל בזק שרוצה להציג קומפוננטה שמציגה את מספר התקפות הסייבר שיש במדינה. מומחי החברה (כלומר מנהל השיווק אחרי שאכטה טובה) בדקו ומצאו שמדובר ב-1200 התקפות. טוב, זה די קל למימוש. ניצור שתי קומפוננטות. אחת CurrentCyberAttackDisplay שעוטפת את המספר ומספקת עיצוב והשניה CurrentCyberAttackCounter שמספקת אך ורק את המספר. הראשונה תכלול את השניה. איך הקוד יראה? כך:

class CurrentCyberAttackDisplay extends React.Component {
  render() {
    const bigStyle = {
      backgroundColor: 'black',
      borderRadius: 10,
      color: 'silver',
      fontSize: '42px',
      textAlign: 'center',
      width: 250,
    };
    const smallStyle = {
      color: 'gold',
      fontSize: '25px',
    };
    return <div style={bigStyle}>
        <CurrentCyberAttackCounter />
        <div style={smallStyle}>Cyber attacks per day</div>
      </div>
  }
}

class CurrentCyberAttackCounter extends React.Component {
  render() {
    const content = <div>1200</div> // This is JSX
    return content;
  }
}

const target = document.getElementById('content');
ReactDOM.render(
  <CurrentCyberAttackDisplay />,
  target
);
1200 Cyber attacks per day קומפוננטת ריאקט
1200 Cyber attacks per day קומפוננטת ריאקט

בשלב הזה של המדריכים, אתם אמורים להבין מעולה את הקוד שלעיל,לא הבנתם? זה הזמן לחזור על המאמרים הקודמים.

מה הבעיה עם הקומפוננטה הזו? מגיע מנהל השיווק ואומר שהוא רוצה שהמספר הזה יעלה בכל 20 שניות ב-100, כדי להלחיץ ולהכניס דינמיות וכדי שהלקוח יילחץ ויזמין את מוצר הסייבר סייברי של החברה. איך עושים את זה? אין לי דרך לעשות את זה אלא באמצעות state . כלומר משתנה בקומפוננטת CurrentCyberAttackCounter שיקבל 1200 והרצה של מתודה שתעלה את המשתנה הזה ב-100 בכל 20 שניות. איך עושים את זה?

הצעד הראשון – יצירת state והצגה שלו. הכי פשוט בעולם. בדיוק בשביל זה אנחנו צריכים constructor. לא יודעים מה זה? לקרוא את המאמר של ES6 קלאסים בקלאסה שיש פה. תתעלמו מהשם הגרוע, הוא תולדה של הקופירייטר הגרוע שיש בי.

בתוך הקונסטרקטור שיהיה ב-CurrentCyberAttackCounter אנחנו נכניס 1200 ל-state.

class CurrentCyberAttackCounter extends React.Component {
  constructor(props) {
    super(props);     
    this.state = {
      attackNumber: 1200,
    };
  }
  
  render() {
    const content =
{ this.state.attackNumber }

// This is JSX return content; } }

זה… זה די פשוט, נכון? לא שונה מתצוגה. אבל עכשיו יש לנו משתנה שאנחנו יכולים לפעול עליו. איך? נכתוב מתודה פשוטה בשם timerTick שמעלה את this.state.attackNumber ב-10 בדיוק.

class CurrentCyberAttackCounter extends React.Component {
  constructor(props) {
    super(props);     
    this.state = {
      attackNumber: 1200,
    };
  }
  
  timerTick() {
    this.setState({attackNumber: this.state.attackNumber + 10});
  }
  
  render() {
    const content =
{ this.state.attackNumber }

// This is JSX return content; } }

זה נהדר אבל מי בדיוק יקרא למתודה הזו? אם אף אחד לא יפעיל את timerTick היא תשכב לה כאבן שאין לה הופכין. אנחנו צריכים פונקציה שתפעל מייד כשהקומפוננטה מתחילה להתרנדר. בדיוק בשביל זה יש לנו את ה-API של ריאקט. בדיוק כמו render, יש לנו את componentDidMount שרצה אך ורק כשהקומפוננטה מוכנה לפעולה. שם נשים את כל מה שאנחנו רוצים לפעול מייד אחרי שהקומפוננטה עובדת. במקרה שלנו, את הקריאה ל-timerTick. או יותר נכון, נשתמש ב-setInterval כדי לקרוא ל-timerTick בכל שניה (1000 מילישניות). איך זה יראה? בדיוק ככה:

class CurrentCyberAttackCounter extends React.Component {
  constructor(props) {
    super(props);     
    this.state = {
      attackNumber: 1200,
    };
  }
  
  timerTick() {
    this.setState({attackNumber: this.state.attackNumber + 10});
  }
  
  componentDidMount() {
    setInterval(this.timerTick, 1000);
  }
  
  render() {
    const content =
{ this.state.attackNumber }

// This is JSX return content; } }

רגע, רגע – יש עוד משהו אחר אחרון. אם אני אריץ את הקוד לעיל הוא לא יעבוד ואקבל שגיאה.

Uncaught TypeError: Cannot read property 'attackNumber' of undefined at timerTick
Uncaught TypeError: Cannot read property 'attackNumber' of undefined
at timerTick

למה? כי כש-timerTick רצה בסקופ של setInterval, היא לא תוכל לגשת ל-this. אנחנו חייבים לעשות לה bind באמצעות:


this.timerTick = this.timerTick.bind(this);

אם אתם מבינים למה, מעולה. אם לא – סימן שאתם צריכים לחזור על סקופינג כי זה מאוד חשוב. במאמר הזה אני כותב על כך. זה חובה להבין למה יש bind כי אנחנו עובדים המון עם סקופינג בריאקט (ובכלל בג׳אווהסקריפט מודרני) וחייבים לדעת את זה אחרת תחטפו שגיאה מימין ומשמאל. הכלל הוא: פונקציה/מתודה שאתם משתמשים בה לא יודעת להגיע למשתנה? יש לכם בעיית סקופינג וצריכים להשתמש ב-bind או ב-call\apply.

והנה, זה הקוד המושלם.

class CurrentCyberAttackDisplay extends React.Component {
  render() {
    const bigStyle = {
      backgroundColor: 'black',
      borderRadius: 10,
      color: 'silver',
      fontSize: '42px',
      textAlign: 'center',
      width: 250,
    };
    const smallStyle = {
      color: 'gold',
      fontSize: '25px',
    };
    return

 

Cyber attacks per day

 

} } class CurrentCyberAttackCounter extends React.Component { constructor(props) { super(props);      this.state = { attackNumber: 1200, }; this.timerTick = this.timerTick.bind(this); } timerTick() { this.setState({attackNumber: this.state.attackNumber + 10}); } componentDidMount() { setInterval(this.timerTick, 1000); } render() { const content =

{ this.state.attackNumber }

// This is JSX return content; } } const target = document.getElementById('content'); ReactDOM.render( , target );

והוא גם יעבוד. נסו ותהנו:

See the Pen React component with state management by Ran Bar-Zik (@barzik) on CodePen.

אז הנה, באמצעות דוגמה אחת הראינו איך עובדים עם stateful components בריאקט. למדנו על constructor שהוא חשוב לאיתחול ה-state ועל componentDidMount שבאמצעותו ניהלנו את ה-state. במאמר הבא נדבר על אירועים בקומפוננטות ריאקט ונעשה דברים קצת יותר אינטראקטיביים. מבטיח.

⚠️אם אהבת את המדריכים על ריאקט – יש ספר מקיף ושלם על ריאקט שכתבתי בשם ללמוד ריאקט בעברית, במסגרת פרויקט עם חברות מובילות ומפתחים אחרים. בספר יש פירוט מקיף יותר על ריאקט ותרגילים רבים ללימוד עצמי. 

פוסטים נוספים שכדאי לקרוא

פתרונות ומאמרים על פיתוח אינטרנט

יישום של nonce על מנת להגן מפני התקפות injection

בפוסט הקודם הסברתי על hash עם CSP על משאבי inline – שזה נחמד ומעולה אבל פחות ישים בעולם האמיתי שבו בדרך כלל התוכן ה-inline (בין

בינה מלאכותית

להריץ ממשק של open-webui על הרספברי פיי

להפעיל ממשק של צ׳אט ג׳יפיטי שאפשר לגשת אליו מכל מחשב ברשת הביתית על רספברי פיי עם מודל בשם tinydolphin שרץ על רספברי פיי.

בינה מלאכותית

Safeguards על מודל שפה גדול (LLM)

פוסט בשילוב עם פודקאסט וסרטון על ההגנות שאפשר להציב על LLM בסביבת פרודקשן

גלילה לראש העמוד