Middleware איננו מושג חדש בפיתוח אינטרנט. כלל מותג בדרך כלל עם פריימוורקים של צד שרת כמו Express.js, שם יש הרבה אימות, לוגינג וכו'. עקב יתרונותיו הנטיים, Middleware הרווח תאוצה משמעותית בצד הלקוח.
פריימוורקים לצד הלקוח כמו React מאמצים אותו כדי לטפל בפונקציות מורכבות בזמן ניהול מצב. במדריך זה, נלמד אתכם את המושג של Middleware ב־React וכיצד להשתמש בו על מנת לשפר את פונקציונאליות האפליקציה שלכם ב־React ולנהל את זרימת היישום בצורה יעילה.
עד סופו, תהיו מבינים טוב איך Middleware ב־React פועל וכיצד ליישם אותו עם Redux Thunk.
Middleware ב־React: מפשט את הלוגיקה של היישום
מה זה Middleware?
כפי ששמו מרמז, Middleware הוא שכבה שיושבת בין רכיבים שונים של אפליקציה. זה מספק שכבת עיבוד ופונקציונליות כאן כשלא היה תהליך כזה בלעדיו. Middleware פועל על ידי יידוש בקשות הזורמות מרכיב אחד לאחר ומאפשר לך לבצע פעולות ספציפיות. לאחר הסיום הוא מעביר את הבקשה המשוננת למידלוואר הבא או ליעד המיועד שלה.
זהו עקרון המשמש בעיקר בצד השרת. אך, כפי שצוין מראש, הוא התאים ב־React כדי לשרת מטרה דומה. כעת, נעקוב אחר מהו Middleware במובן ספציפי, ברמת React.
Middleware ב־React
ב־React, middleware מיושם כסדרה של פונקציות, שמבוצעות אחת אחרי השנייה, בסדר שאתה מגדיר. כל פונקציה מקבלת גישה למצב ולפעולות של האפליקציה. לכן, הפונקציות יכולות לשנות ולשחרר פעולות חדשות.
כאשר מצב משתנה ב־React, האפליקציה משחררת פעולות שאז מטופלות על ידי ה־Reducer(s). ה־Reducer(s) אז יחזירו מצב חדש, שאז מאוחסן ומועבר בחזרה לאפליקציה.
Middleware ב־React יושב בין הפעולה שנשחררת ומתפסת אותה לפני שהיא מגיעה ל־reducer. לאחר מכן, זה מאפשר לך להתחבר לתהליך זה ולהריץ קוד מסוים על הפעולה הזו, לדוגמה, לרשום אותה או לבצע שיחת API.
פעם שזה נעשה, זה יעביר את הפעולה ששונתה ל־Reducer (אם אין middleware אחר בשרשרת).
דוגמאות ל־Middleware ב־React
אתה יכול למצוא Middleware ב־React בעיקר ב־Redux, ספריית ניהול מצב מורכבת ל־React. Redux כולל שני סוגי Middleware עיקריים:
- Thunk – נעמק עמוק יותר באיך להשתמש במידלוואר הזה כדי לשנות פעולה.
- Saga.
כל אחד מטפל בסוגים שונים של שינויים לפעולות, כפי שנראה למטה כאשר נבחן את השימושים במידלוואר ב־React. ספריות אחרות של React, כמו React Query, גם משתמשות ב־Middleware (יותר על כך מאוחר יותר).
לפני שנסתכל על איך ליישם את זה, בואו נעבור על השימושים השונים במידלוואר ב־React.
שימושים של Middleware ב־React
React middleware מועיל למטרות השימוש הבאות:
ניפוי שגיאות ולוגים
React middleware יכול לשמש לרישום מידע כגון מצב נוכחי, פעולות ונתונים נוספים במהלך פיתוח היישום. יתר על כן, אלה יכולים להיות שימושיים לזיהוי באגים פוטנציאליים ושגיאות לפתרון מוקדם.
ה-Redux Logger (ל-Redux) יכול לעזור לך בכך. הוא מפעיל לוגים על פעולות Redux ושינויים במצב לצורך ניפוי שגיאות קל. הוא מפנה כל פעולה שנשלחת ומספק לוגים על המצב הקודם, הפעולה והמצב הבא.
אימות ואימות זהות
אם ברצונך לאמת משתמשים לפני שאתה מעדכן מצב, ניתן להשתמש ב-Redux Thunk או Saga כדי לטפל בזרימות האימות. לאחר שאתה מפנה פעולה זו, middleware זה מאפשר לך לאחסן טוקנים, לבדוק אימות לפני שהוא מפנה את הפעולה, או לרענן טוקנים.
במילים אחרות, middleware אלה שימושיים לבדיקה האם משתמש מאומת לגישה לנתיב מסוים או לא.
פעולות המבוססות על אירועים
ה-React reducer מיועד להפעלת קוד סינכרוני. זה אומר שאם תנסה להפעיל כל שהוא אסינכרוני עליו, זה לא יעבוד. בעזרת middleware כגון Redux Thunk, ניתן לתפוס את הפעולה, לבצע משימות אסינכרוניות כמו קריאת API, ולהמשיך ל-reducer פעם שזה נעשה.
אחסון נתונים
React Query (middleware נוסף של React) יכול לשמש ככלי יעיל במידע של אפליקציית המטמון. הוא מטמן תגובות API באופן אוטומטי ומבצע חידוש שלהן כאשר נדרש. כתוצאה מכך, הוא עוזר לך למנוע שיחות API מיותרות על ידי בדיקה של המידע הנדרש במטמון.
שיפור ביצועים
מידע של React יכול גם לעזור לשפר את ביצועי האפליקציה על ידי השהיית פעולות בלתי נחוצות למועד מאוחר יותר, השהיית אירועים ועיבוד מטופל של משימות מסוימות. על ידי מטילת תגובות API, React Query גם משפר את ביצועי האפליקציות שלך ב-React.
איך להשתמש ב-Middleware ב-React?
Redux הוא כלי עוצמתי לניהול מצב גלובלי באפליקציות React. זה כולל מספר middleware בתיקיית הכלים שלו שניתן להשתמש בהם כדי להוסיף פונקציונליות מותאמת אישית לאפליקציות ה-React שלך. אחד הנפוצים ביותר הוא Redux Thunk.
מבוא ל-Redux Thunk
לפני שנתפקד עמוק ביותר למימוש של Thunk, בואו נאסוף מידע מסוים עליו כך שנוכל להשתמש בו ביעילות.
מהו Thunk?
בתכנות כללי, "Thunk" הוא פשוט פונקציה שמשמשת להשהות את הערך ואת ביצוע הפונקציה. אנו יכולים לראות אותו כפונקציה שמדחה פעולה עד שתנדרש תנאי מסוים.
ב-Redux, Thunk הוא פונקציה ספציפית המשמשת עם middleware של Redux Thunk. Redux Thunk מיועד לאפשר פעולות אסינכרוניות באפליקציה שלך ב-React. כמו שציינו בעבר, ה-Reducer בנוי להריץ קוד סינכרוני. זה אומר שכאשר נשלחת פעולה, ה-Reducer מעדכן את המצב מיידית.
רדוקס Thunk כ Middleware
רדוקס Thunk פועל כ middleware. זה מאפשר לך לכתוב action creators שמחזירים פונקציות (thunks) במקום אובייקטי פעולה פשוטים. פונקציות אלו יכולות להכיל לוגיקה אסינכרונית. כאשר אתה מפעיל thunk, middleware ה-Thunk מפנה אותו ומבצע את הפונקציה.
בתוך ה־thunk
, אתה יכול לבצע את הפעולה האסינכרונית שלך (למשל, לבצע קריאה ל-API) ולאחר מכן לשדר פעולות רגילות כדי לעדכן את חניית ה־Redux כאשר הפעולה הושלמה.
הערה: רדוקס Thunk מאפשר פעולות אסינכרוניות וסינכרוניות, אף על פי שמטרתו העיקרית היא לסייע בפעולות אסינכרוניות. זה לא מונע ממך לשדר פעולות סינכרוניות; הוא פשוט מספק מנגנון לטיפול בפעולות אסינכרוניות גם.
עם זה מאוחזת, בואו נראה את middleware של React בפעולה על ידי הטמעת Redux Thunk.
מדריך שלב אחרי שלב להטמעת Redux Thunk
הטמעת middleware של Redux כוללת את השלבים הבאים:
שלב 1: הגדר את Uפ Redux עם Thunk
צור אפליקציית React והתקן את התלותי הבאות.
npx create-react-app newApp
שלב 2: התקן את Redux Thunk
הרץ את הפקודה הבאה כדי להתקין Redux Thunk.
npm install redux-thunk
שלב 3: אפשר Middleware של Thunk
Enable the Thunk middleware in the Redux store.
import { configureStore } from '@reduxjs/toolkit';
import thunk from 'redux-thunk';
import rootReducer from './reducers'; // Combine all reducers here
const store = configureStore({
reducer: rootReducer,
middleware: [thunk],
});
export default store;
הערה: כאשר משתמשים ב־Redux Toolkit, אין צורך להתקין את thunk
באופן פשוט.
שלב 4: כתיבת פונקציה אסינכרונית
פונקציית Thunk מחזירה פונקציה נוספת שמקבלת את הארגומנטים dispatch
ו־getstate
כדי לקרוא את המצב או לשלוח פעולות. הנה קוד הדוגמה לקבלת נתונים:
// סוגי פעולות
const START_FETCH = 'START_FETCH';
const FETCH_SUCCESS = 'FETCH_SUCCESS';
const FETCH_ERROR = 'FETCH_ERROR';
// יוצרי פעולות
const startFetch = () => ({ type: START_FETCH });
const fetchSuccess = (data) => ({ type: FETCH_SUCCESS, payload: data });
const fetchError = (error) => ({ type: FETCH_ERROR, payload: error });
// פעולת Thunk
export const fetchData = () => {
return async (dispatch, getState) => {
dispatch(startFetch()); // Notify that the fetch has started
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
if (!response.ok) {
throw new Error('Failed to fetch data');
}
const data = await response.json();
dispatch(fetchSuccess(data)); // Send the fetched data to the store
} catch (error) {
dispatch(fetchError(error.message)); // Handle any errors
}
};
};
שלב 5: טיפול בפעולות שנשלחו ב־Reducer
טפלו בפעולות שנשלחו על ידי עדכון ה־reducer.
const initialState = {
data: [],
isLoading: false,
error: null,
};
export const dataReducer = (state = initialState, action) => {
switch (action.type) {
case START_FETCH:
return { ...state, isLoading: true, error: null };
case FETCH_SUCCESS:
return { ...state, isLoading: false, data: action.payload };
case FETCH_ERROR:
return { ...state, isLoading: false, error: action.payload };
default:
return state;
}
};
שלב 6: שליחת Thunk מרכיב
השתמשו ב־hook useDispatch
כדי לשלוח thunks בפרוייקטים של React.
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchData } from './actions';
const DataComponent = () => {
const dispatch = useDispatch();
const { data, isLoading, error } = useSelector((state) => state.data);
useEffect(() => {
dispatch(fetchData()); // Trigger the thunk to fetch data
}, [dispatch]);
if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;
return (
<ul>
{data.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
);
};
export default DataComponent;
שימוש ב־createAsyncThunk
ה־Redux Toolkit מכיל API מובנה שמגדיר לוגיקה ברמה גבוהה לפונקציות אסינכרוניות, שולח פעולות אליהן ומטפל בשגיאות מיד. יש לשים לב שמאחר שזה מספק הסתרה עבור מקרים המסוימים של פונקציות אסינכרוניות, createAsyncThunk
לא נחוץ לכל מקרה השימוש ב־thunks.
הנה קוד המימוש הדוגמתי של createAsyncThunk
:
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
export const dataFetch = createAsyncThunk('data/fetchData', async () => {
const response = await fetch('https://api.example.com/data');
return response.json();
});
const dataSlice = createSlice({
name: 'data',
initial_State: { data: [], loading: false, error: null },
extraReducers: (builder) => {
builder
.addCase(dataFetch.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(dataFetch.fulfilled, (state, action) => {
state.loading = false;
state.data = action.payload;
})
.addCase(dataFetch.rejected, (state, action) => {
state.loading = false;
state.error = action.error.message;
});
},
});
export default dataSlice.reducer;
עכשיו, כדי לשלוח את ה־thunk dataFetch
, השתמשו בקוד הבא:
dispatch(dataFetch ());
שימושים של Middleware של React – Redux Thunk
Thunks ניתן להשתמש בהם למגוון מטרות, כולל אך לא מוגבל ל:
- הסתרת לוגיקה מורכבת מהרכיבים.
- ביצוע בקשות אסינכרוניות ולוגיקה.
- כתיבת פונקציות לשליחת מספר פעולות בסדר.
React Middleware in Other State Management Libraries
Redux לא היא הספרייה היחידה ב-React שמשתמשת ב- middleware. בנוסף, תוכל למצוא אותם גם בספריות ניהול מצב אחרות, אם כי המימוש של המושג הזה בספריות אלה שונה מאופן המימוש של Redux.
MobX
MobX אין לו middleware מסורתי כמו Redux. הוא מציע פונקציונליות דומה דרך מנגנונים כגון interceptors, observers, ו-reactions. מנגנונים אלו מאפשרים לך לצפות בשינויים במצב ה-MobX שלך ולהגיב אליהם. בצורה זו, MobX מספק דרכים לטיפול באפקטים צדדיים, לוגינג, ומשימות אחרות שממושג middleware טיפל בדרך כלל ב-Redux.
Recoil
Recoil אינו תומך ב- middleware באותה דרך כמו Redux מכיוון שאין לו צורך בכך. הוא מאפשר לך לעדכן ישויות במצב (אטומים) ישירות באמצעות פונקציות ספציפיות. אין פעולת מעבירה של פעולות למטפל, אותן תוכל להפריע עם middleware. כדי לטפל בפעולות אסינכרוניות, הוא משתמש ב-selectors – מצב מובן על פי אטומים או selectors אחרים.
Zustand
זה עוזר לנהל מצבים ב-API פשוט ותומך ב- middleware טבעי ללוגינג ולאחסון מצבים, בדיוק כמו Redux.
XState
XState תומך בהתנהגות דומה ל- middleware באמצעות hooks כמו onTransition
, actions
, ומשרות. חוקים אלו מסייעים להפריע ולשנות את המעברים במצב.
Conclusion
Middleware פועל כגשר לחיבור ושילוב של רכיבים שונים באפליקצית האינטרנט לזרימת נתונים וטיפול טוב יותר. הם נמצאים בשימוש רחב בצד השרת מאז זמן רב, אך כעת נמצאים בשימוש גם בצד הלקוח.
ב-React, קיימים דרכים שונות ליישום של middleware. הם נמצאים בדרך כלל מקושרים לספריות ניהול המצב כגון Redux ו-MobX. ה-middleware של React הנפוץ ביותר, Thunk, כלול בספריית Redux. Thunk הוא קטע קוד שמבצע משימות מאוחרות.
במאמר זה, חקרנו Middleware ב-React, ספריית Redux, ו-Redux Thunk. גילינו גם את השלבים ליישום middleware של Redux Thunk לקבלת נתונים ושיחרוז פעולות.
Source:
https://dzone.com/articles/demystifying-react-middleware-bridging-apis-and-co