איך להציג עץ ב React עם טבלה ו React.Fragment

02/07/2021

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

1. המידע

בשביל המשחק בחרתי מידע היררכי המכיל צבע וכל מיני דברים באותו הצבע. זה האוביקט:

const data = [
  {
    data: { color: "blue" },
    childItems: [
      {
        data: { color: "blue", name: "blueberry" }
      },
      {
        data: { color: "blue", name: "water" }
      },
      {
        data: { color: "blue", name: "whale" }
      }
    ]
  },
  {
    data: { color: "green" },
    childItems: [
      {
        data: { color: "green", name: "cucumber" }
      },
      {
        data: { color: "green", name: "frog" }
      }
    ]
  }
];

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

תצוגת עץ של מידע זה תציג קודם כל את הכותרת Blue, אחרי זה את רשימת כל הפריטים הכחולים, אחר כך שורה עם הכותרת Green ואז את כל הפריטים הירוקים.

2. הקומפוננטה

דרך קלה להציג את המידע היא פשוט טבלה בה כל פעם שצריך "להיכנס" פנימה לילדים של פריט נוסיף אינדנטציה לשורה. אז תהיה לי שורה עם blue ואז בשורה שאחריה יהיו התאים blue ו blueberry שיתחילו באינדנטציה קצת יותר ימינה. איתם יחד באותה אינדנטציה תופיע גם השורה השלישית עם blue ו water עד שבסוף נגיע ל green שיחזור לאינדנטציה של blue.

הקוד עבור הקומפוננטה הוא בסך הכל:

function Tree(props) {
  const { data, renderRow, depth } = props;
  if (!data) {
    return false;
  }
  return data.map((row, index) => (
    <>
      {renderRow(row.data, index, depth)}
      {<Tree data={row.childItems} depth={depth + 10} />}
    </>
  ));
}

Tree.defaultProps = {
  renderRow: (data, index, depth) => (
    <tr>
      <td style={{ paddingLeft: `${depth}px` }}>{data.color}</td>
      <td>{data.name}</td>
    </tr>
  ),
  depth: 10
};

כל Tree הוא בסך הכל רשימה של שורות (נוצרות על ידי הפונקציה renderRow), ואחרי כל שורה רשימת כל ה"עצים" שנוצרים מהילדים שלה. השימוש ב Tree בתוך Tree ימשיך להפעיל את הפונקציה בצורה רקורסיבית כדי להציג את העץ כולו, ובזכות השימוש ב Fragment כל פונקציה יכולה להחזיר אוסף של שורות בלי "לקלקל" את התוצאה עם div עוטף.

אפשר לראות את הקוד בפעולה בקודסנדבוקס הבא: https://codesandbox.io/s/hopeful-swirles-36oe9?file=/src/App.js

3. מה הלאה

ההרפקתנים ביניכם מוזמנים לקחת את המשחק הזה צעד אחד קדימה ולאפשר למשתמש להסתיר או להציג כל קבוצה של ילדים, כלומר להציג + קטן ליד השורה עם blue ו + קטן נוסף ליד השורה עם green, ולא להציג את 5 השורות עם המידע המלא. כשמשתמש ילחץ על הפלוס הקטן יוצגו כל הילדים של אותו פריט והפלוס יהפוך למינוס.

רמז: שימו לב לסטייט, איפה שומרים אותו ומה בדיוק צריך להישמר.