קודקודייל
  • קודקודייל
  • מי אתם קודקודייל?
  • קורסים בחינם
  • צרו קשר
  • בניית אתרים
    • וורדפרס
  • נגישות אתרים
  • כל הקטגוריות
    • אנגולר
    • HTML
    • CSS
    • Javascript
    • Typescript
    • NodeJs
    • בלוקציין
  • קודקודייל
  • מי אתם קודקודייל?
  • קורסים בחינם
  • צרו קשר
  • בניית אתרים
    • וורדפרס
  • נגישות אתרים
  • כל הקטגוריות
    • אנגולר
    • HTML
    • CSS
    • Javascript
    • Typescript
    • NodeJs
    • בלוקציין
קודקודייל
  • קודקודייל
  • מי אתם קודקודייל?
  • קורסים בחינם
  • צרו קשר
  • בניית אתרים
    • וורדפרס
  • נגישות אתרים
  • כל הקטגוריות
    • אנגולר
    • HTML
    • CSS
    • Javascript
    • Typescript
    • NodeJs
    • בלוקציין
  • קודקודייל
  • מי אתם קודקודייל?
  • קורסים בחינם
  • צרו קשר
  • בניית אתרים
    • וורדפרס
  • נגישות אתרים
  • כל הקטגוריות
    • אנגולר
    • HTML
    • CSS
    • Javascript
    • Typescript
    • NodeJs
    • בלוקציין
ראשי ♦ Typescript ♦ מודדים ביצועים עם ריאקט – React Profiler

מודדים ביצועים עם ריאקט – React Profiler

וינר יאיר 5 באפריל 2022 אין תגובות

כל מי שעובד עם ריאקט בטח מכיר את "בעיית הרינדורים של ריאקט" אם להיות כנה אני לא חושב שזו בעייה, יש כאלו שיגידו שריאקט מרנדר את הDOM סתם וגורם לבעיות ביצועים (performance) ואז צריך להשתמש בכל מיני טכניקות שנראות קצת מיותרות\ חוזרות על עצמן כמו למשל useMemo, memo .

אז דעתי היא שזה בסדר גמור לרנדר! לא לדאוג מזה בכלל, יש דברים שאין להם כל חשיבות ברמת ביצועים ואין סיבה סתם להעמיס פונקציונליות על כל פיפס(או להעמיס בזיכרון). אז איפה כן יש לזה חשיבות? ואיך אפשר לבדוק זאת?

מה שאפשר למדוד אפשר לשפר – React Profiler

בשביל לשפר את ביצועי הUI שאתם מיישמים אתם ככל הנראה משתמשים בDEV TOOLS של הדפדפן שלכם. אבל לא תמיד נוח להשתמש בו וכן הוא מסובך למדי במידה ורוצים למדוד ביצועים של כל מיני תרחישים שקורים בצד הלקוח. ולכן אני ממליץ לכם להשתמש בתוסף קטן שנקרא React Developer Tool ויכול להיות חלקכם מכירים אותו כי מאד נוח לעבוד איתו, אבל האם יצא לכם לעבוד עם טאב ה profiler ?

לפני שניגש לעבודה עם profiler ונכיר את היכולות שלו , נבנה דוגמה פשוטה מאד על מנת לתרגל ולהגדים וכך נבין טוב יותר את הנושא.

import React, { useState } from 'react';
import './App.css';
import List from './List';





function App() : JSX.Element {
 
  const [counter, setCounter] = useState<number>(0);

  return (
    <div className="App">
       <div className="counter-container">
    <span>{counter}</span>
    <button onClick={()=>setCounter(counter+1)}>+</button>
  </div>
        <List listCount={21} />
    </div>
  );
}

export default App;
import React from 'react';

function List(props: {listCount:number}) : JSX.Element {
  return (
    <div className="list-container">
        <ul>
           { Array.from(Array(props.listCount).keys()).map((item)=>{return (<Item key={item} item={item} />)})}
        </ul>
    </div>
  )
}

export default List;
import React from 'react'

 function Item({item}: {item: number}) :JSX.Element {
  return (
    <li>{item}</li>
  )
}

export default Item;
* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background-color: #282c34;
}

.App {
  text-align: center;
}

.counter-container {
  padding: 20px 30px;
  border-radius: 10px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  background-color: #fff;
  max-width: 200px;
  margin: 30px auto;
  display: flex;
  justify-content: space-between;
}

.counter-container span {
  font-size: 30px;
  color: #282c34;
}

.counter-container button {
  background-color: salmon;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: none;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  font-size: 20px;
  color: #fff;
  cursor: pointer;
  transform: all 0.2s;
}

.counter-container button:active {
  background-color: rgb(208, 94, 81);
}

.list-container ul {
  list-style: none;
  padding: 0;
  max-width: 240px;
  margin: 0 auto;
}

.list-container ul li {
  display: inline-block;
  padding: 10px 20px;
  border-radius: 10px;
  background: #fff;
  margin: 2px;
}

כל מה שיש לנו פה זה בסה"כ רכיב אחד של רשימה שלא עושה שום דבר ואיזה כפתור שמשנה את הSTATE של APP. ומה שקורה במקרה הזה הוא שכל הרכיבים מתרנדרים כולל LIST שאין בו כל שימוש אז אין באמת סיבה לרנדר אותו,.. בואו נודה גם שבמקרה הזה, זה לא באמת משנה. אבל אם תשנו את הרשימה ל20,000 אייטמים, האם זה סבבה שכל קליק הרשימה תטרנדר ? התשובה לזה כבר לא חלקות דעות שאנחנו יכולים למדוד .

איך מודדים עם React Profiler

נתחיל בסקירה קצרה , כך נראה לשונית ה profiler :

React Profiler
React Profiler

אם אצלכם זה נראה שונה, אז זה כי שיניתי מעט ההגדרות, תוכו להגדיר גם dark mode או להישאר עם הלבן. אבל משהו שאתם רוצים לאפשר זה highlight כאשר הרכיבים מתרנדרים וככה אתם יכולים לראות בעיניים אילו מהרכיבים מתרנדרים בו ברגע. לדוגמה:

אינדיקטור לרנדור רכיבים בריאקט
אינדיקטור לרנדור רכיבים בריאקט

הכפתור החשוב ביותר עבורנו בשימוש ב react profiler הוא ה record. כפתור בפינה השמאלית למעלה עושה את רוב הקסם. כול שעליכם לעשות הוא ללחוץ עליו ואז לגשת לאפליקציה שלנו וללחוץ על הכפתור של הוספה ולחזור ותוסף ולהפסיק את ההקלטה. ואז תראה כמה דברים מעניינים מאד:

react profiler record
react profiler record

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

אם תשנו את כמות האייטמים לנגיר 20 אל. תראו שזמן זה יתארך . וכפי שכולנו יודעים, אין סיבה בכלל שהרכיב יתרפרש בכלל. אז מה עושים?

קודם כל כמובן שאפשר למנוע רינדורים מיותרים בפירוק טוב יותר של הרכיבים והSTATE . אבל לפעמים אין לנו את האפשרות הזו. ולכן מגיעים לעזרתנו הוקים שימושיים כגון useMemo ו- memo.

React Memo, useMemo

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

השימוש בMemo

עם Memo נוכל לעטוף רכיבים שלא נרצה שיתרנדרו שלא לצורך . אם המידע לא משתנה בהם אין סיבה לרנדר אותם. להלן המימוש:

import React, {memo} from 'react';
import Item from './Item';

function List(props: {listCount:number}) : JSX.Element {
  return (
    <div className="list-container">
        <ul>
           { Array.from(Array(props.listCount).keys()).map((item)=>{return (<Item key={item} item={item} />)})}
        </ul>
    </div>
  )
}

export default memo(List);

ועכשיו כשתנסו להקליט עם profiler אתם תראו שכל הרכיב של LIST לא מתרנדר וכך חסכתם לא מעט בביצועים!. שאלה שאולי נשאלת בראשכם זה למה לא לעטוף את כל הרכיבים עם MEMO וזהו? אז קודם כל לריאקט יש את המכניזם שלה ויש סיבה שהם לא בחרו בכך וכפי שציינתי ממקודם, MEMO עולה לנו, ואנחנו לא רוצים להעמיס על הזכרון בדפדפן ולכן צריך לעשות חשבון מושכל איפה להשתמש בMEMO.

עוד עניין שחשוב לזכור זה שMEMO עושה SALLOW COMPARISON מה שזה אומר שהטיפול הרינדור יעיל עבור משתנים פרימיטיבים. אם נעביר פונקציה או אובייקט מורכב ככל הנראה MEMO לא יעשה את עבודתו כראוי.

React useMemo

כתבנו בעבר פוסט על ההוק הזה ומי שרוצה להיזכר יכול להיכנס מדריך ריאקט – react hooks | useMemo & useCallback
ובהמשך לפוס שלנו על memozation וכפי שציינו שMEMO לא אפקטיפי על פונקציות למשל אז useMemo בא לעזרתנו. נוכל לעטוף פונקציונאליות שימנעו רינדורים מיותרים. כמו כן נוכל גם להגדיר במערך התלויות עבור משתנים שיאזין להם, כמו כן המשתנה(או המשתנים) שיש לו חשיבות לפונקציה שאותה החלטתם לעטוף עם useMemo.

לסיכום – פוסט מודדים ביצועים עם ריאקט – React Profiler

הסיכום שלי הוא פשוט למדי, כל מה שעליכם לעשות זה לאמץ עבודה עם React Profiler . רכיבים שהינם "זולים" ברינדור אין סיבה לשמור בקאש עם memo או useMemo . אבל אם מדדתם וראיתם שהרינדור עלול להיות יקר, אז להשתמש בהתאם. בהצלחה 🐊✌

פוסטים קשורים:

מדריך ריאקט – react hooks | useMemo & useCallbackמדריך ריאקט – react hooks | useMemo & useCallback מדריך ריאקט שיעור useReducerמדריך ריאקט – react hooks | useReducer מדריך ריאקט – react hooks | Custom Hook מדריך ריאקט שיעור useContextמדריך ריאקט – react hooks | useContext
memo reactjs useMemo לימוד ריאקט מדריך חינם react מדריך ריאקט קורס ריאקט

אודות המחבר

יאיר וינר להציג את כל הפוסטים של וינר יאיר


« פוסט קודם
פוסט הבא »

השארת תגובה

ביטול

חיפוש באתר
בחירת העורכים
29 בדצמבר 2023 עידן יצחקי

שדה טקסט עשיר עם תמונות

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

1 באוקטובר 2021 עידן יצחקי

איך למשוך דינמית favicon של אתרים אחרים ב-JS

בפוסט זה נראה איך אפשר על פי לינקים בדף למשוך את ה-favicon מהדומיין שלהם באופן דינמי, בדיקה של תקינות התמונה

פופולרי
Javascript functions – היכרות עם סוגי פונקציות
Javascript
21 בדצמבר 2024 אין תגובות
Nested routing in angular standalone component
Typescript
15 בנובמבר 2024 תגובה אחת
בחרו לפי תגיות
angular blockchain css ethers express front-end fullstack GQL html javascript next js nextjs nodejs react hooks reactjs solidity webgl אנגולר בלוקציין וורדפרס לימודי אנגולר לימודי וורדפרס לימוד ריאקט מדריך front-end מדריך GQL מדריך אנגולר מדריך וורדפרס מדריך חינם react מדריך ריאקט מפתח בלוק מפתח בלוקציין מתכנת front-end מתכנת בלוקציין מתכנת פרונט סולידיטי קורס front end קורס fullstack קורס nextjs קורס אנגולר קורס בלוקציין קורס בלוקציין בחינם קורס סולידיטי קורס ריאקט קורס תכנות קורס תכנות בחינם
סינון על פי קטגוריות
CSS fullstack HTML IIS Javascript nodeJs SEO Typescript אנגולר בלוקציין בניית אתרים וורדפרס חיפוש עבודה כלים נוספים כללי נגישות קורסים ריאקט תלת מימד תקלות ופתרונות
צור קשר
כל הזכויות שמורות לקודקודייל
ליצירת קשר: @ קודקודייל
גלילה לראש העמוד