الوسيط ليس مفهومًا جديدًا في تطوير الويب. عادةً ما يرتبط بإطارات العمل الخلفية مثل Express.js، حيث يوجد الكثير من المصادقة والتسجيل، إلخ. نظرًا لمزاياه الكامنة، اكتسب الوسيط جاذبية كبيرة في الواجهة الأمامية.
تعتمد إطارات الواجهة الأمامية مثل React عليها كطريقة للتعامل مع وظائف معقدة أثناء إدارة الحالة. في هذا الدليل، سنرشدك خلال مفهوم الوسيط في React وكيفية استخدامه لتعزيز وظائف تطبيق React الخاص بك وإدارة تدفق التطبيق بفعالية.
بحلول النهاية، ستكتسب فهمًا جيدًا لما هو وسيط React وكيفية تنفيذه مع Redux Thunk.
تبسيط وسيط React: تبسيط منطق التطبيق
ما هو الوسيط؟
كما يوحي الاسم، الوسيط هو طبقة تقع بين مكونات مختلفة في تطبيق. يوفر طبقة معالجة ووظيفة هنا عندما لا يكون هناك واحد بدونه. يعمل الوسيط عن طريق التقاط الطلبات المتدفقة من مكون إلى آخر ويسمح لك بتنفيذ إجراءات محددة. بمجرد الانتهاء يمرر الطلب المعدل إلى الوسيط التالي أو الوجهة المقصودة.
هذا هو مفهوم يستخدم في الأساس في الخلفية. ولكن، كما ذكر سابقًا، تم تكييفه في React لخدمة غرض مماثل. الآن، دعنا نتعمق في ما يعنيه الوسيط، على وجه التحديد في React.
الوسيط في React
في React، يتم تنفيذ البرمجيات الوسيطة كسلسلة من الوظائف، يتم تنفيذها واحدة تلو الأخرى، بالترتيب الذي تحدده. كل وظيفة لديها وصول إلى حالة التطبيق وإجراءاته. وبالتالي، يمكن للوظائف تعديل وإرسال إجراءات جديدة.
عندما تتغير الحالة في React، يقوم التطبيق بإرسال إجراءات يتم التعامل معها بعد ذلك بواسطة المقلل (Reducer). سيعيد المقلل (المقللات) بعد ذلك حالة جديدة، والتي يتم تخزينها وإعادتها إلى التطبيق.
تجلس البرمجيات الوسيطة في React بين الإجراء المرسل وتقوم باعتراضه قبل أن يصل إلى المقلل. ثم، يسمح لك بالانخراط في هذه العملية وتنفيذ بعض الأكواد على هذا الإجراء، على سبيل المثال، تسجيله أو إجراء مكالمة API.
بمجرد الانتهاء من ذلك، ستقوم بتمرير الإجراء المعدل إلى المقلل (إذا لم يكن هناك برمجيات وسيطة أخرى في السلسلة).
أمثلة على البرمجيات الوسيطة في React
يمكنك العثور على البرمجيات الوسيطة في React بشكل أساسي في Redux، مكتبة إدارة الحالة المعقدة في React. لدى Redux نوعان رئيسيان من البرمجيات الوسيطة:
- Thunk – سنتناول كيف يمكن استخدام هذه البرمجيات الوسيطة لتعديل إجراء.
- Saga.
كل منهما يتعامل مع أنواع مختلفة من التعديلات على الإجراءات، كما سنرى أدناه عند النظر في استخدامات البرمجيات الوسيطة في React. تستخدم مكتبات React الأخرى، مثل React Query، أيضًا البرمجيات الوسيطة (المزيد عن ذلك لاحقًا).
قبل أن نلقي نظرة على كيفية تنفيذ ذلك، دعنا نستعرض الاستخدامات المختلفة للبرمجيات الوسيطة في React.
استخدامات البرمجيات الوسيطة في React
الوسيط البرمجي لـ React يأتي بمتناول لحالات الاستخدام التالية:
تصحيح الأخطاء وتسجيل الأحداث
يمكن استخدام الوسائط البرمجية لـ React لتسجيل المعلومات مثل الحالة الحالية، والإجراءات، وغيرها من البيانات أثناء تطوير التطبيق. وعلاوة على ذلك، يمكن أن تكون هذه مفيدة لتحديد الأخطاء والأخطاء المحتملة للقيام بالحلول المبكرة.
يمكن أن يساعدك سجل Redux (لـ Redux) في القيام بذلك. يقوم بتسجيل إجراءات Redux وتغييرات الحالة لتصحيح الأخطاء بسهولة. يعترض كل إجراء يتم إرساله ويسجل الحالة السابقة، والإجراء، والحالة التالية.
التفويض والمصادقة
إذا كنت ترغب في التحقق من هوية المستخدمين قبل تحديث الحالة، يمكنك استخدام Redux Thunk أو Saga للتعامل مع سير العمل للمصادقة. بمجرد أن تعترض إجراءً، تمكّنك هذه الوسيطة من تخزين الرموز، والتحقق من المصادقة قبل إرسال الإجراء، أو تحديث الرموز.
بعبارة أخرى، هذه الوسائط البرمجية مفيدة للتحقق مما إذا كان المستخدم مصادقًا للوصول إلى مسار معين أم لا.
العمليات المدفوعة بالأحداث
مُصمم مُخفض React لتشغيل الرموز المتزامنة. هذا يعني أنه إذا حاولت تشغيل أي شيء غير متزامن عليه، فلن يعمل. مع وسائط React مثل Redux Thunk، يمكنك التقاط الإجراء، وأداء المهام غير المتزامنة مثل عمل مكالمة API، والمضي قدمًا إلى المخفض بمجرد الانتهاء من ذلك.
تخزين البيانات
يمكن لـ React Query (وسيط React آخر) أن يكون أداة فعالة في تخزين بيانات التطبيق. يقوم بتخزين استجابات واجهة برمجة التطبيقات تلقائيًا وإعادة التحقق من صحتها عند الحاجة. ونتيجة لذلك، يساعدك على تجنب استدعاءات واجهة برمجة التطبيقات المكررة من خلال التحقق من المعلومات المطلوبة في التخزين المؤقت.
تحسين الأداء
يمكن لوسيط React أيضًا المساعدة في تحسين أداء التطبيق عن طريق تأجيل الإجراءات غير الضرورية لاحقًا، وتأخير الأحداث، ومعالجة دُفعية لبعض المهام. من خلال تخزين استجابات واجهة برمجة التطبيقات، يعزز React Query أيضًا أداء تطبيقات React الخاصة بك.
كيفية استخدام الوسيط في React؟
Redux هي أداة قوية لإدارة الحالة العامة في تطبيقات React. تشمل عدة وسيطات في مجموعة أدواتها يمكنك استخدامها لإضافة وظائف مخصصة إلى تطبيقات React الخاصة بك. واحدة من الأكثر شيوعًا هي Redux Thunk.
مقدمة لـ Redux Thunk
قبل الانغماس في تنفيذ Thunk، دعنا نجمع بعض المعلومات حوله حتى نتمكن من استخدامه بفعالية.
ما هو Thunk؟
في البرمجة العامة، “Thunk” هو ببساطة دالة تُستخدم لتأجيل تقييم وتنفيذ دالة. يمكننا النظر إليه على أنه دالة تؤجل إجراء حتى يتم تحقيق شرط معين.
في Redux، يعتبر Thunk دالة محددة تُستخدم مع وسيط Redux Thunk. تم تصميم Redux Thunk للسماح بالعمليات الغير متزامنة داخل تطبيق React الخاص بك. في وقت سابق ذكرنا أن المُخفض مُبني لتشغيل رموز متزامنة. وهذا يعني أنه عندما يتم توجيه إجراء، يُحدث المُخفض الحالة على الفور.
Redux Thunk كوسيط
يعمل Redux Thunk كوسيط. يتيح لك كتابة مُنشئي الإجراءات التي تعيد وظائف (الثانكس) بدلاً من كائنات إجراء عادية. يمكن أن تحتوي هذه الوظائف على منطقية غير متزامنة. عندما ترسل ثانك، يعترض مُعالج الـ Thunk ذلك وينفذ الوظيفة.
داخل thunk
، يمكنك القيام بالعملية الخاصة بك غير المتزامنة (على سبيل المثال، إجراء مكالمة API) ثم إرسال الإجراءات العادية لتحديث مخزن Redux عند اكتمال العملية.
ملاحظة: يتيح Redux Thunk كل من العمليات غير المتزامنة والمتزامنة، على الرغم من أن الغرض الرئيسي منه هو تيسير الإجراءات غير المتزامنة. إنه لا يمنعك من إرسال إجراءات متزامنة؛ بل يوفر ببساطة آلية للتعامل مع الإجراءات غير المتزامنة أيضًا.
بعد ذلك، دعنا نرى عمل مُعالج React عن طريق تنفيذ Redux Thunk.
دليل خطوة بخطوة لتنفيذ Redux Thunk
تتضمن تنفيذ الوسيط Redux الخطوات التالية:
الخطوة 1: قم بتعيين Up Redux بـ Thunk
قم بإنشاء تطبيق React وتثبيت التبعيات.
npx create-react-app newApp
الخطوة 2: قم بتثبيت Redux Thunk
قم بتشغيل الأمر التالي لتثبيت Redux Thunk.
npm install redux-thunk
الخطوة 3: تمكين وسيط 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: كتابة دالة Async
الـ 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: التعامل مع الأوامر التي تم إرسالها في المحدد
تعامل مع الأوامر التي تم إرسالها من خلال تحديث المحدد.
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 من عنصر
استخدم خطاف 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 على واجهة برمجة التطبيقات المضمنة التي تحدد المنطق مستوى عالٍ للوظائف الـ async، وترسلها، وتعالج الأخطاء بسرعة. يُرجى ملاحظة أنه نظرًا لأنه يوفر تجريدًا لحالات الاستخدام المحددة للوظائف الـ async، فإن 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 لمجموعة من الأغراض، بما في ذلك وليس على سبيل الحصر:
- تجريد المنطق المعقد من المكونات.
- إجراء طلبات ومنطق async.
- كتابة وظائف لإرسال عدة أوامر على التوالي.
وسائط React في مكتبات إدارة الحالة الأخرى
لا تعتبر Redux المكتبة الوحيدة في React التي تستفيد من الوسائط. يمكنك أيضاً العثور عليها في مكتبات إدارة الحالة الأخرى، على الرغم من أن تنفيذ هذا المفهوم في هذه المكتبات يختلف عن كيفية القيام بذلك في Redux.
MobX
لا تمتلك MobX وسائط تقليدية مثل Redux. إنها تقدم وظائف مشابهة من خلال آليات مثل المعترضات، والمراقبين، والتفاعلات. تتيح لك هذه الآليات مراقبة التغييرات في حالة MobX الخاصة بك والتفاعل معها. بهذه الطريقة، توفر MobX طرقاً للتعامل مع الآثار الجانبية، والتسجيل، وغيرها من المهام التي تتعامل معها الوسائط عادةً في Redux.
Recoil
لا تدعم Recoil الوسائط بنفس الطريقة التي تدعمها بها Redux لأنها لا تحتاج لذلك. إنها تتيح لك تحديث أجزاء الحالة (الذرات) مباشرةً باستخدام وظائف محددة. لا يوجد إرسال للإجراءات إلى المخفض، الذي يمكنك اعتراضه بواسطة الوسائط. للتعامل مع العمليات غير المتزامنة، تستخدم المحددات — الحالة المستمدة اعتماداً على الذرات أو محددات أخرى.
Zustand
تساعد في إدارة الحالات من خلال واجهة برمجة تطبيقات بسيطة وتدعم الوسائط الأصلية لتسجيل وتخزين الحالات، تماماً مثل Redux.
XState
يدعم XState سلوكاً يشبه الوسائط باستخدام الخطافات مثل onTransition
, actions
, و services
. تساعد هذه الخطافات في اعتراض وتعديل انتقالات الحالة.
الخاتمة
الوسيط يعمل كجسر لربط ودمج مكونات مختلفة من تطبيق ويب لتحسين تدفق ومعالجة البيانات. لقد تم استخدامها على نطاق واسع على الجانب الخلفي منذ ذلك الحين، ولكن الآن وجدت حالات استخدام على الواجهة الأمامية أيضا.
في React، هناك طرق مختلفة لتنفيذ الوسيط. عادة ما تكون مرتبطة بمكتبات إدارة الحالة مثل Redux، وMobX. الوسيط الأكثر استخدامًا في React، Thunk، مضمن في مكتبة Redux. الثانك هو كتلة كود تقوم بأداء المهام المؤجلة.
في هذه المقالة، قمنا باستكشاف الوسائط في React، ومكتبة Redux، و Redux Thunk. كما تمت مراجعة خطوات تنفيذ وسيط Redux Thunk لاسترجاع البيانات وإرسال الإجراءات.
Source:
https://dzone.com/articles/demystifying-react-middleware-bridging-apis-and-co