עשר דקות עם Tanstack Router
עכשיו ש React Router עדכנו שוב את הגירסה, הפעם כדי להפוך לפריימוורק במיזוג עם Remix, אני חושב שהגיע הזמן לבחון אפשרויות אחרות, והאפשרות הפופולרית ביותר היום מלבד React Router היא Tanstack Router. בואו נראה קצת קוד לדוגמה כדי להבין איך זה עובד. קוד הדוגמה של הפוסט זמין בגיטהאב בקישור:
1. קובץ ה Layout
טנסטאק ראוטר, בדומה ל next.js, עובד לפי שמות קבצים. הוא מתחבר ל vite וכל פעם שאנחנו רצים במצב פיתוח או בנייה הוא מחפש את הקבצים שנראים כמו נתיבים בתיקייה ויוצר מכולם יחד קובץ מידע מרוכז על נתיבים, בו הוא ישתמש בקוד כדי לספק Type Safety, כלומר אלמנט Link יוכל לדעת אם הוא מוביל למקום שבאמת מתאים לנתיב מתוך ה Router ואם היתה שגיאת כתיב אז נוכל לראות את זה כבר בזמן כתיבת הקוד.
בשביל להתקין את Tanstack Router יש תהליך די מסורבל שמפורט בדף ההתקנה שלהם:
https://tanstack.com/router/latest/docs/framework/react/installation
בגדול מוסיפים אותו ל vite, וטוענים אותו מהקובץ הראשי ביישום.
אחרי ההתקנה אפשר ליצור את קבצי הנתיבים וקובץ הנתיב הראשי בדוגמה שלהם נקרא __root.tsx
. זה הקוד שהם כתבו עם קצת שינויים שלי:
import { createRootRoute, Link, Outlet } from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/router-devtools'
export const Route = createRootRoute({
component: () => (
<>
<div className="p-2 flex gap-2">
<Link to="/" className="[&.active]:font-bold">
Home
</Link>{' '}
<Link to="/about" className="[&.active]:font-bold ">
About
</Link>
<Link
to="/posts/$postId"
params={{postId: "7"}}
className="[&.active]:font-bold ">
Read Post
</Link>
</div>
<hr />
<Outlet />
<TanStackRouterDevtools />
</>
),
})
הפקודה createRootRoute
אומרת שמדובר בנתיב ראשי כלומר קובץ Layout. אוביקט ה component שלה הוא הקומפוננטה הראשית של העמוד ובתוכו קומפוננטת Outlet תציג את התוכן האמיתי כלומר את הקומפוננטה שמתאימה לנתיב הנוכחי. מעל ה Outlet יש לנו תפריט ניווט ומתחת יש לנו קומפוננטה של כלי פיתוח. כלי הפיתוח זה בעצם חלון צף קטן שנותן המון מידע על ה Router והנתיבים השונים בו.
2. קבצי הנתיבים
שני הקבצים האחרים בתוכנית הדוגמה שהוצעה בתיעוד הם about.lazy.tsx
ו index.lazy.tsx
. השם שלהם כבר מסמן לנו שמדובר בנתיבים עצלים, כלומר שהקוד שלהם ייטען רק כשמשתמש ייכנס אליהם בפעם הראשונה. כך נראה תוכן הקובץ about.tsx
:
import { createLazyFileRoute, Link } from '@tanstack/react-router'
export const Route = createLazyFileRoute('/about')({
component: About,
})
function About() {
return <div className="p-2">
Hello from About!
<Link to='/'>Type Safe?</Link>
</div>
}
לא מסובך: הפקודה createLazyFileRoute
מקבלת את הנתיב וקומפוננטה ומוסיפה אותו לרשימת הנתיבים (זאת שנוצרת בצורה אוטומטית בקובץ routeTree.gen.ts
). ה Link שמופיע שם הוא Type Safe, כלומר אם אני מנסה לכתוב משהו שלא מתאים לשום נתיב מופיע שם קו אדום בגלל הטייפסקריפט.
3. נתיב דינמי
בשביל המשחק יצרתי קובץ נוסף בשם posts/$postId.lazy.tsx
עם התוכן הבא:
import { createLazyFileRoute } from '@tanstack/react-router'
export const Route = createLazyFileRoute('/posts/$postId')({
component: Post,
})
function Post() {
const { postId } = Route.useParams()
return <div className="p-2">This is post number: {postId}</div>
}
שם הקובץ כבר מרמז לנו שיש פה משהו מיוחד. הדולר בתחילת שם הקובץ אומר ש postId
זה שם של פרמטר ובאמת בתוך גוף הקומפוננטה אני יכול להשתמש ב useParams
כדי לגשת לערך של אותו פרמטר. פה אפשר להוציא בקשת רשת כדי למשוך מידע לגבי אותו פוסט לפי המזהה שלו, או להיעזר במנגנון ה Data Fetching המובנה של Tanstack Router (עליו אולי אכתוב בפוסט אחר) כדי לשלב את הראוטר עם מנגנון שליפת המידע.
4. על מה אפשר להתלונן?
ראוטרים נהיו מאוד מסובכים בשנים האחרונות וטאנסטאק ראוטר, למרות היותו עדיין יותר פשוט מ React Router, עדיין נשאר במגרש של הראוטרים המסובכים. מה שמסבך אותו לדעתי זה מנגנון ה Data Fetching המובנה, שמכריח את הראוטר לכלול כלים לניהול ה Cache של המידע שמגיע מהשרת. אישית העדפתי את הימים ששני המנגנונים האלה היו באחריות ספריות שונות - כלומר אפשר היה להשתמש ב react-query או RTK Query בשביל שליפת מידע ובספריה אחרת בשביל הניתוב. בכל מקרה זה בסך הכל חלומות נוסטלגיים שלי כי לא נראה שתהיה דרך חזרה.
ספציפית לגבי Tanstack Router התלונה היחידה שלי היא שבגלל הטייפסקריפט הוא יכול להיות קצת נודניק. קודם כל בשביל שקובץ ה routeTree.gen.ts
יתעדכן הפרויקט צריך לרוץ במצב פיתוח, כלומר npm run dev
צריך לעבוד. נכון רוב הזמן אני משאיר אותו דולק אבל לפעמים אני גם כותב קוד כשהוא סגור ואז צריך להתעצבן שהטייפסקריפט לא מזהה את הנתיבים שיצרתי.
דוגמה שניה היא נתיבים עם פרמטרים, שדורשים תחביר מיוחד ב Link:
<Link to="/posts/$postId" params={{postId: "7"}}>Post 7</Link>
ניסיון לכתוב את זה בתור מחרוזת פשוטה שובר את טייפסקריפט, כלומר זה לא עובד:
<Link to="/posts/7">Post 7</Link>
אבל מלבד הבעיות עם הטייפסקריפט העבודה עם טנסטאק בהחלט נעימה. ניתוב בעזרת מערכת קבצים עוזר לשמור על סדר בפרויקט וגם דרך הטיפול שלהם בפרמטרים מאוד ברורה רק מהסתכלות על מערכת הקבצים.
בפוסטים הבאים אני מקווה להמשיך לחקור אותו ולכתוב יותר לעומק על Data API, על הטיפול ב Redirects ועל פקודות ניתוב מתוך הקוד.