איתור שגיאות בתוכנית ריאקט

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

1. שימוש בכלי איתור השגיאות של הדפדפן

הפעילו את הפרויקט שכתבנו בשיעור הקודם על המכונה שלכם ומתוך דפדפן כרום לחצו כפתור ימני ובחרו Inspect Element. כנסו לטאב Sources והרחיבו את התיקייה src. בתוכה נמצא שני קבצים מעניינים:

  1. הקובץ App.jsx מכיל את הקוד כמו שאנחנו כתבנו אותו ב VS Code.

  2. הקובץ App.jsx ואחריו סימן שאלה ו t שווה מספר מכיל את הקוד כמו שהדפדפן רואה אותו.

לפעמים לא נראה את הסימן שאלה ו t בשם הקובץ ואז נצטרך להבדיל לפי ההטייה - שם הקובץ כמו שאנחנו כתבנו ב VS Code כתוב בכתב מוטה הצידה והקובץ שהדפדפן רואה כתוב בגופן רגיל.

מבחינת הדפדפן כל סימני ה JSX לא קיימים, אבל זה לא משנה - כשאנחנו מסתכלים על הקוד מתוך כלי הפיתוח של הדפדפן תמיד נבחר להסתכל על הקובץ App.jsx שמתאים לקוד שאנחנו כתבנו.

יותר מזה - אנחנו יכולים לסמן נקודות עצירה בקובץ והדפדפן יעצור בדיוק בשורה שרצינו. בואו ננסה את זה. עדכנו את הקוד של הקומפוננטה Person לקוד הבא:

function Person({name = "Guest"}) {
  const nameInUppercase = name.toUpperCase();

  return (
    <h1>Hello {nameInUppercase}</h1>
  )
}

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

2. סוגי שגיאות

בעבודה על יישום ריאקט אנחנו ניתקל ב-3 סוגי שגיאות וחשוב להכיר ולדעת להבדיל בין הסוגים:

  1. שגיאות בניה - זה מה שקורה כש vite לא מצליח לתרגם את הקוד שכתבנו ב VS Code לקוד שדפדפן יכול לקרוא.

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

  3. שגיאות בתוך render של קומפוננטה - אלו שגיאות זמן ריצה שקורות כשריאקט מנסה להבין איך צריכות להיראות הקומפוננטות.

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


function Person({name = "Guest"}) {
  const nameInUppercase = name.toUpperCase();

  return (
    <h1>Hello {nameInUppercase}</h1>
    <p>Nice to see you</p>
  )
}

אנחנו רואים ש VS Code מציג קו אדום מתחת ל JSX. אחרי שמירת הקובץ וחזרה לדפדפן אנחנו רואים שם הודעת שגיאה ענקית עם התוכן הבא:

[plugin:vite:react-babel] C:\Users\ynonp\react\04-debug\after\hello-react-world\src\App.jsx: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>? (8:4)
  11 |
C:/Users/ynonp/react/04-debug/after/hello-react-world/src/App.jsx:8:4
6  |    return (
7  |      <h1>Hello {nameInUppercase}</h1>
8  |      <p>Nice to see you</p>
   |      ^
9  |    )
10 |  }

שגיאות כאלה נקראות שגיאות בנייה בגלל שהקוד אף פעם לא הגיע לדפדפן. אנחנו רואים שמי שזרק את השגיאה זה vite כי הוא לא הצליח לתרגם את הקוד.

נמחק את הפיסקה ונעבור לראות שגיאה מסוג שני - שגיאת JavaScript רגילה שקורית מחוץ להצגת הקומפוננטות. בשביל זה אני כותב פונקציה חדשה בקובץ App.jsx:

function hasError() {
  const x = 10;
  x += 5;
  console.log(x);
}

וגם משנה את הקומפוננטה App.jsx ומוסיף לה כפתור, כך שלחיצה על הכפתור תפעיל את הפונקציה:

function App() {
  return (
    <>
      <Person name="a" />
      <Person name="b" />
      <button onClick={hasError}>Click Me</button>
      <Person />
    </>
  )
}

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

react-dom_client.js?v=173dcb84:3748 Uncaught TypeError: Assignment to constant variable.
    at hasError (App.jsx:5:3)
    at HTMLUnknownElement.callCallback2 (react-dom_client.js?v=173dcb84:3672:22)
    at Object.invokeGuardedCallbackDev (react-dom_client.js?v=173dcb84:3697:24)
    at invokeGuardedCallback (react-dom_client.js?v=173dcb84:3731:39)
    at invokeGuardedCallbackAndCatchFirstError (react-dom_client.js?v=173dcb84:3734:33)
    at executeDispatch (react-dom_client.js?v=173dcb84:7014:11)
    at processDispatchQueueItemsInOrder (react-dom_client.js?v=173dcb84:7034:15)
    at processDispatchQueue (react-dom_client.js?v=173dcb84:7043:13)
    at dispatchEventsForPlugins (react-dom_client.js?v=173dcb84:7051:11)
    at react-dom_client.js?v=173dcb84:7175:20

ואנחנו גם רואים שפקודת ה console.log שהיתה צריכה לסיים את הפונקציה לא בוצעה. כשפונקציה זורקת Exception המהלך התקין של הפונקציה נפגע אבל זה לא ישפיע על שאר הדברים בתוכנית.

הסוג השלישי של שגיאות שאנחנו נראה הן Exceptions שנזרקים מתוך הקוד שצריך להחזיר לריאקט את ה Virtual DOM, כלומר מתוך קוד הקומפוננטה. במצב כזה ריאקט לא יודע מה הוא צריך להציג על המסך. נעדכן את הקובץ App.jsx שוב הפעם נמחק את הגדרת ערך ברירת המחדל למשתנה name בקומפוננטה Person:

import './App.css'

function hasError() {
  const x = 10;
  x += 5;
  console.log(x);
}

function Person({name}) {
  const nameInUppercase = name.toUpperCase();

  return (
    <h1>Hello {nameInUppercase}</h1>
  )
}

function App() {
  return (
    <>
      <Person name="a" />
      <Person name="b" />
      <button onClick={hasError}>Click Me</button>
      <Person />
    </>
  )
}

export default App

הפעלה חוזרת של התוכנית מראה לנו הפעם מסך לבן. רק בכלי הפיתוח אנחנו יכולים לראות את השגיאה:

Uncaught TypeError: Cannot read properties of undefined (reading 'toUpperCase')
    at Person (App.jsx:10:32)
    at renderWithHooks (react-dom_client.js?v=173dcb84:11566:26)
    at mountIndeterminateComponent (react-dom_client.js?v=173dcb84:14944:21)
    at beginWork (react-dom_client.js?v=173dcb84:15932:22)
    at beginWork$1 (react-dom_client.js?v=173dcb84:19779:22)
    at performUnitOfWork (react-dom_client.js?v=173dcb84:19224:20)
    at workLoopSync (react-dom_client.js?v=173dcb84:19163:13)
    at renderRootSync (react-dom_client.js?v=173dcb84:19142:15)
    at recoverFromConcurrentError (react-dom_client.js?v=173dcb84:18762:28)
    at performConcurrentWorkOnRoot (react-dom_client.js?v=173dcb84:18710:30)

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

  1. אם זו שגיאת בנייה אנחנו נראה הודעת שגיאה ענקית על מסך הדפדפן שמגיעה מ vite.

  2. אם זו שגיאת זמן ריצה מחוץ לבניית הקומפוננטות אנחנו נראה אותה ב console.

  3. אם זו שגיאת זמן ריצה בזמן שריאקט מנסה להפעיל את פוקנציות הקומפוננטות אנחנו נראה מסך לבן ושגיאה ב console.

3. תוסף כלי הפיתוח של ריאקט

כלי נוסף שיכול לעזור לנו בעבודה עם ריאקט להבין איזה קומפוננטות יש על המסך ומה הפרמטרים של כל קומפוננטה הוא תוסף כלי הפיתוח של ריאקט. מתקינים את התוסף רגיל מה Chrome Web Store בקישור: https://chromewebstore.google.com/detail/fmkadmapgofadopljbjfkapdkoienihi

לאחר התקנת התוסף תקבלו טאב חדש בשם Components במסך כלי הפיתוח שם תוכלו לראות את עץ הקומפוננטות של ריאקט. לחיצה על קומפוננטה תראה לנו את הפרמטרים שהיא קיבלה מהקומפוננטה שיצרה אותה וגם תצבע בדפדפן את המיקום של אותה קומפוננטה. דרך התוסף אפשר לשנות את ה props ולראות בצורה מיידית את ההשפעה.