חיפוש
  • יניב אור

מערכת ניהול - React - חלק 7

עודכן ב: מרץ 21

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


תיקונים ועדכונים

עשיתי עוד כמה שינויים ונקיונות. את כל קבצי ה-constants שהיו מפוזרים בתיקיות השונות במערכת ריכזתי בתיקיה אחת constants תחת src. דבר נוסף, את הקריאות API עם axios, שהיו כתובות בקובץ actions עצמו העברתי לקובץ api.js תחת services. אם ארצה בעתיד להשתמש בספריה אחרת ולא ב-axios, כך יהיה קל יותר לעשות את השינוי. בכל מקרה, זה הרבה יותר נקי ומסודר בצורה הזאת.


הפונקציה getItems לפני התיקון:


הפונקציה getItems אחרי התיקון:

הפונקציה apiRequest נמצאת, כאמור, בקובץ נפרד.


src/services/api.js

אני בוחר האם לשלוח קריאת GET להבאת הנתונים, POST לשמירה של רשומה חדשה או PUT לעדכון רשומה - בבדיקת האובייקט data. אם data לא קיים, סימן שזה get. אם קיים ויש id - זה put. אחרת post. לא יודע אם אהבתי עד הסוף את מה שעשיתי פה אבל בינתיים זה מספיק טוב. סך הכל זה קוד קטן, נפרד מכל שאר הקוד ואפשר בקלות לשנות אותו בלי לעשות מהפכות בשאר המערכת.


טפסים

נתחיל עם ה-UI. אני מזכיר את מבנה עץ הרכיבים. יש לנו, תחת התיקיה components, תיקיית Views עם רכיבים שלרוב יהיו מקושרים ל-route מסוים. דף משתמשים (Accounts), למשל, או דף פוסטים (Posts). הרכיבים הללו משתמשים ברכיב כללי יותר שאחראי להציג כותרת, טבלה וטופס - כרגע. הרכיב הוא Entity. הוא נמצא בתיקיית Views ובהמשך אעביר אותו למקום מתאים יותר. אולי ל-Layout. אנחנו מתעסקים כרגע עם הרכיב Form.

src/components/Views/Entity.js

באמצעות ה-useSelector אני משתמש בערכים fields ו-selectedRow מה-store - ב-Entity ומעביר אותם כמאפיינים לרכיב Form. הפרמטר fields מחזיק את ההגדרות לשדות בטופס, לייבלים וכן הלאה. selectedRow הוא האובייקט של הפריט הנוכחי עליו עובדים כרגע. אני לא מעוניין לשנות את הערכים ישירות ברשימת תוצאות. כך אוכל לשחזר את המידע (בעזרת הכפתור reset, למשל) במידה והמשתמש התחרט.


מאפיינים נוספים אותם אני מעביר לטופס הם הפונקציות fieldChanged, submitForm, resetForm, clearForm - שקוראות ל-action creators בהתאם.


רכיב ה-Form נראה כך:


src/components/Common/Form/index.js

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



בכל שינוי ערך באחד השדות, נשלחת קריאה - דרך Entity - לאקשן FIELD_CHANGED עם הפרמטרים field (שם השדה) ו-value (הערך).


src/store/actions/entities/index.js (החלק הרלוונטי)


אני מעדכן את selectedRow עם הערך החדש לשדה המתאים - ב-reducer שמטפל באקשן המדובר:


src/store/reducers/entities/main.js (החלק הרלוונטי)


נתייחס לכפתורים Reset ו-New והפונקציות resetForm ו-clearForm - בהתאמה - ונעבור ישר ל-reducers.


src/store/reducers/entities/main.js (החלק הרלוונטי)

הפונקציה resetRowId אוספת את המידע על ה-row הנוכחי מרשימת הרשומות המלאה ומעדכנת את selectedRow. אם הטופס היה ריק - במצב של הוספה ולא עדכון - ה-selectedRow יקבל אובייקט ריק. הפונקציה clearRowId מאפסת את selectedRow גם היא עם אובייקט ריק.


בלחיצה על כפתור Submit ברכיב Form - נשלחת קריאה לפונקציה submitForm וממנה קריאה ל-saveItem שנמצאת בקובץ actions.


src/store/actions/entities/index.js (החלק הרלוונטי)

כמו בכל פעולה אסינכרונית מהסוג הזה, אני פותח action ל-started - לפני הפעולה. action נוסף ל-succeeded - במידה והפעולה הצליחה. ו-action נוסף ל-failed. בשני המקרים, גם ב-getItems וגם ב-saveItem - במידה והקריאה לשרת הצליחה - אני קורא לפונקציה getProcessedItems שמחשבת שוב ומחזירה את מספרי השורות אותן צריך להציג על המסך בטבלה.


נעבור ל-reducers.

src/store/reducers/entities/main.js (החלק הרלוונטי)

בשלושת המצבים יש עדכון של ה-saveState הרלוונטי. מעבר לזה, ב-saveItemSucceeded יש עדכון ל-selectedRow מהמידע (row) שהתקבל מהשרת ויש עדכון ל-rows עם ה-row החדש.



המשך בחלק הבא:

מערכת ניהול - React - חלק 8


© 2023 by DO IT YOURSELF. Proudly created with Wix.com