يقول مؤلف المادة ، التي ننشر ترجمتها اليوم ، أنه جزء من فريق
Hike messenger ، الذي يشارك في ميزات جديدة للتطبيق. هدف هذا الفريق هو الترجمة إلى الواقع واستكشاف الأفكار التي قد يحبها المستخدمون. وهذا يعني أن المطورين بحاجة إلى التصرف بسرعة ، وأنهم يضطرون غالبًا إلى إجراء تغييرات على الابتكارات التي يبحثون عنها ، والتي تهدف إلى جعل تجربة المستخدم مريحة وممتعة قدر الإمكان. يفضلون إجراء تجاربهم باستخدام React Native ، حيث تعمل هذه المكتبة على تسريع عملية التطوير وتسمح لك باستخدام نفس الرمز على منصات مختلفة. بالإضافة إلى ذلك ، يستخدمون مكتبة Redux.

عندما يبدأ مطورو Hike في العمل على شيء جديد ، عند مناقشة بنية الحل الذي تم التحقيق فيه ، لديهم عدة أسئلة:
- هذه فرصة تجريبية يمكن ، كما يقولون ، "عدم الطيران" ، ويجب التخلي عنها. بالنظر إلى ذلك ، هل من الضروري قضاء الوقت في تصميم بنية التطبيق؟
- التطبيق التجريبي هو مجرد MVP ، وهو منتج قابل للتطبيق إلى الحد الأدنى يحتوي على 1-2 شاشات ويحتاج إلى إنشائه في أسرع وقت ممكن. بالنظر إلى هذا ، هل يجب علي الاتصال بـ Redux؟
- كيف تبرر الوقت الذي يستغرقه مديرو المنتجات لإعداد البنية التحتية الداعمة لتطبيق تجريبي؟
في الواقع ، يساعدك Redux في العثور على الإجابات الصحيحة لكل هذه الأسئلة. تساعد بنية Redux على فصل حالة التطبيق عن React. يسمح لك بإنشاء مستودع عالمي يقع في المستوى الأعلى من التطبيق وتوفير وصول الدولة لجميع المكونات الأخرى.
فصل المسؤوليات
ما هو "فصل المسؤوليات"؟ إليك ما تقوله
ويكيبيديا عن ذلك: "في علم الكمبيوتر ، تقسيم المسؤوليات هو عملية تقسيم برنامج الكمبيوتر إلى كتل وظيفية تتداخل مع وظائف بعضها البعض بقدر الإمكان. في حالة أكثر عمومية ، تقسيم المسؤوليات هو تبسيط عملية واحدة لحل مشكلة من خلال تقسيمها إلى عمليات تفاعل لحل المهام الفرعية. "
تسمح لك بنية Redux بتنفيذ مبدأ فصل المسؤوليات في التطبيقات ، وتقسيمها إلى أربع كتل ، كما هو موضح في الشكل التالي.
الهندسة المعمارية Reduxفيما يلي وصف موجز لهذه الكتل:
- تشبه الإقرارات أو مكونات واجهة المستخدم (مكونات واجهة المستخدم) الوظائف النقية (أي تلك الوظائف التي لا تغير البيانات المنقولة إليها ولها بعض الخصائص الأخرى) المسؤولة عن عرض المعلومات على الشاشة بناءً على البيانات المنقولة إليها من المتجر. لا يغيرون البيانات مباشرة. عندما يقع حدث ما ، أو إذا تفاعل المستخدم معهم ، يلجأون إلى منشئي الإجراءات.
- إن منشئو الأفعال مسؤولون عن إنشاء وإرسال الإجراءات.
- يتلقى المخفضون الإجراءات المجدولة وتحديث حالة المستودع.
- مخزن البيانات مسؤول عن تخزين بيانات التطبيق.
اعتبر هندسة Redux كمثال.
ماذا لو احتاجت المكونات المختلفة إلى نفس البيانات؟
يحتوي تطبيق Hike على شاشة تعرض قائمة أصدقاء المستخدم. يتم عرض المعلومات الخاصة بكميتها أعلى هذه الشاشة.
شاشة الأصدقاء في تطبيق Hikeهناك 3 مكونات تفاعل هنا:
FriendRow
هو مكون يحتوي على اسم صديق المستخدم وبعض المعلومات الأخرى عنه.FriendsHeader
- مكون يعرض نقش "أصدقائي" ومعلومات حول عدد الأصدقاء.ContainerView
هو مكون حاوية يجمع بين عنوان الشاشة الذي يمثله مكون FriendsHeader
وقائمة الأصدقاء التي تم الحصول عليها عن طريق اجتياز مصفوفة تحتوي على معلومات حول أصدقاء المستخدم ، ويتم عرض كل عنصر منها على الشاشة بواسطة مكون FriendRow
.
هذا هو الرمز الخاص بـ
friendsContainer.js لتوضيح ما سبق:
class Container extends React.Component { constructor(props) { super(props); this.state = { friends: [] }; } componentDidMount() { FriendsService.fetchFriends().then((data) => { this.setState({ friends: data }); }); } render() { const { friends } = this.state; return ( <View style={styles.flex}> <FriendsHeader count={friends.length} text='My friends' /> {friends.map((friend) => (<FriendRow {...friend} />)) } </View> ); } }
من الطرق الواضحة تمامًا لإنشاء صفحة تطبيق مثل تحميل البيانات حول الأصدقاء إلى مكون الحاوية وتمريرها كخصائص إلى المكونات الفرعية.
دعونا نفكر في حقيقة أن هذه البيانات حول الأصدقاء قد تكون مطلوبة في بعض المكونات الأخرى المستخدمة في التطبيق.
تنزه شاشة الدردشةافترض أن التطبيق يحتوي على شاشة دردشة ، والتي تحتوي أيضًا على قائمة الأصدقاء. يمكن ملاحظة أنه يتم استخدام نفس البيانات على الشاشة مع قائمة الأصدقاء وعلى شاشة الدردشة. ماذا تفعل في موقف مماثل؟ لدينا خياران:
- يمكنك تنزيل بيانات صديقك مرة أخرى في مكون
ComposeChat
المسؤول عن عرض قوائم الدردشة. ومع ذلك ، فإن هذا النهج ليس جيدًا بشكل خاص ، نظرًا لأن استخدامه سيعني ازدواجية البيانات ويمكن أن يؤدي إلى مشاكل في المزامنة. - يمكنك تنزيل بيانات عن الأصدقاء في مكون المستوى الأعلى (الحاوية الرئيسية للتطبيق) ونقل هذه البيانات إلى المكونات المسؤولة عن عرض قائمة الأصدقاء وقائمة غرف الدردشة. بالإضافة إلى ذلك ، نحتاج إلى تمرير الوظائف إلى هذه المكونات لتحديث بيانات الأصدقاء ، وهو أمر ضروري لدعم مزامنة البيانات بين المكونات. سيؤدي هذا النهج إلى حقيقة أن مكون المستوى الأعلى سيتم تعبئته حرفياً بالطرق والبيانات التي لا يستخدمها بشكل مباشر.
كلا هذين الخيارين ليسا جذابين للغاية. الآن دعونا نلقي نظرة على كيفية حل مشكلتنا باستخدام بنية Redux.
باستخدام Redux
هنا نتحدث عن تنظيم العمل باستخدام البيانات باستخدام التخزين ومنشئي الإجراء والمخفضات ومكونين لواجهة المستخدم.
▍1. مستودع البيانات
يحتوي المستودع على بيانات تم تحميلها عن أصدقاء المستخدم. يمكن إرسال هذه البيانات إلى أي مكون في حالة الحاجة إليها هناك.
▍2. منشئو الأكشن
في هذه الحالة ، يتم استخدام منشئ الإجراء لإرسال الأحداث التي تهدف إلى حفظ وتحديث البيانات عن الأصدقاء. هنا هو رمز
friendsActions.js :
export const onFriendsFetch = (friendsData) => { return { type: 'FRIENDS_FETCHED', payload: friendsData }; };
▍3. المخفضات
المخفضون ينتظرون الأحداث التي تمثل الإجراءات المقررة للوصول وتحديث أصدقائهم. هنا هو رمز
لأصدقاء Reducer.js :
const INITIAL_STATE = { friends: [], friendsFetched: false }; function(state = INITIAL_STATE, action) { switch(action.type) { case 'FRIENDS_FETCHED': return { ...state, friends: action.payload, friendsFetched: true }; } }
▍4. مكون قائمة الأصدقاء
يقوم مكون الحاوية هذا بعرض بيانات الأصدقاء وتحديث الواجهة عند تغييرها. بالإضافة إلى ذلك ، فهو مسؤول عن تنزيل البيانات من المستودع إذا لم يكن لديه. هذا هو الرمز الخاص
بالأصدقاء. Container.js :
class Container extends React.Component { constructor(props) { super(props); } componentDidMount() { if(!this.props.friendsFetched) { FriendsService.fetchFriends().then((data) => { this.props.onFriendsFetch(data); }); } } render() { const { friends } = this.props; return ( <View style={styles.flex}> <FriendsHeader count={friends.length} text='My friends' /> {friends.map((friend) => (<FriendRow {...friend} />)) } </View> ); } } const mapStateToProps = (state) => ({ ...state.friendsReducer }); const mapActionToProps = (dispatch) => ({ onFriendsFetch: (data) => { dispatch(FriendActions.onFriendsFetch(data)); } }); export default connect(mapStateToProps, mapActionToProps)(Container);
▍5. مكون قائمة الدردشة
يستخدم مكون الحاوية هذا أيضًا البيانات من التخزين ويستجيب لتحديثه.
حول تطبيق Redux Architecture
قد يستغرق الأمر يومًا أو يومين لإحضار البنية الموصوفة أعلاه إلى حالة العمل ، ولكن عندما يلزم إجراء تغييرات على المشروع ، يتم إجراؤها ببساطة وبسرعة. إذا كنت بحاجة إلى إضافة مكون جديد إلى التطبيق الذي يستخدم بيانات عن الأصدقاء ، فيمكنك القيام بذلك دون القلق بشأن مزامنة البيانات أو أنه سيتعين عليك إعادة مكونات أخرى. وينطبق نفس الشيء على إزالة المكونات.
الاختبار
عند استخدام Redux ، يمكن اختبار كل كتلة تطبيق بشكل مستقل.
على سبيل المثال ، يمكن إخضاع كل مكون لواجهة المستخدم بسهولة لاختبار الوحدة ، لأنه مستقل عن البيانات. النقطة هي أن دالة تمثل مثل هذا المكون دائمًا ما ترجع نفس التمثيل لنفس البيانات. هذا يجعل التطبيق قابل للتنبؤ ويقلل من احتمال حدوث الأخطاء أثناء تصور البيانات.
يمكن اختبار كل مكون بشكل شامل باستخدام مجموعة متنوعة من البيانات. يكشف هذا الاختبار عن مشكلات خفية ويساعد على ضمان جودة عالية للرمز.
وتجدر الإشارة إلى أنه ليس فقط المكونات المسؤولة عن تصور البيانات ، ولكن أيضًا المخفضات ومنشئو العمل يمكن أن يخضعوا لاختبار مستقل.
Redux رائع ، ولكن باستخدام هذه التكنولوجيا واجهنا بعض الصعوبات.
صعوبات باستخدام Redux
template كود القالب الزائد
من أجل تنفيذ بنية Redux في أحد التطبيقات ، عليك قضاء الكثير من الوقت ، مع مواجهة جميع أنواع المفاهيم والكيانات الغريبة.
هذه هي ما يسمى الزلاجات (thunks) ، المخفضات (المخفضات) ، الإجراءات (الإجراءات) ، الطبقات الوسيطة (middlewares) ، هذه هي وظائف
mapStateToProps
و
mapDispatchToProps
، بالإضافة إلى المزيد. يستغرق الأمر وقتًا لتعلم كل هذا ، ولتعلم كيفية استخدامه بشكل صحيح ، يلزم الممارسة. هناك الكثير من الملفات في المشروع ، على سبيل المثال ، قد يؤدي إجراء تغيير طفيف واحد في مكون التمثيل المرئي للبيانات إلى إجراء تغييرات على أربعة ملفات.
قبو Red Redux هو مفرد
في Redux ، تم بناء مستودع البيانات باستخدام نمط المفرد ، على الرغم من أن المكونات يمكن أن يكون لها مثيلات متعددة. غالبًا ما لا تكون هذه مشكلة ، ولكن في حالات معينة ، يمكن أن يؤدي مثل هذا النهج لتخزين البيانات إلى بعض الصعوبات. على سبيل المثال ، تخيل أن هناك حالتين لمكون. عندما تتغير البيانات في أي من هذه الحالات ، تؤثر هذه التغييرات على مثيل آخر. في حالات معينة ، قد لا يكون هذا السلوك مرغوبًا فيه ؛ قد يكون من الضروري لكل مثيل للمكون استخدام نسخته الخاصة من البيانات.
الملخص
تذكر سؤالنا الرئيسي ، وهو ما إذا كان الأمر يستحق الوقت والجهد لتنفيذ بنية Redux. نحن ، ردًا على هذا السؤال ، نقول Redux "نعم". تساعد هذه البنية على توفير الوقت والجهد في تطوير التطبيقات وتطويرها. يسهّل استخدام Redux على المبرمجين إجراء تغييرات متكررة على التطبيق ، ويجعل الاختبار أسهل. بالطبع ، توفر بنية Redux مقدارًا كبيرًا من التعليمات البرمجية المتداخلة ، ولكنها تساعد على تقسيم الشفرة إلى وحدات مناسبة للعمل معها. يمكن اختبار كل وحدة من هذه الوحدات بشكل مستقل عن غيرها ، مما يساعد على تحديد الأخطاء في مرحلة التطوير ويسمح بضمان برامج عالية الجودة.
أعزائي القراء! هل تستخدم Redux في مشاريعك؟
