:: فروع شركة الحمد (آخر رد :soha mag)       :: فروع شركة الحمد (آخر رد :soha mag)       :: المحامية رباب المعبي : حكم لصالح موكلنا بأحقيتة للمبالغ محل الدعوى (آخر رد :غوايش)       :: المحامية رباب المعبي : حكم لصالح موكلنا بأحقيتة للمبالغ محل الدعوى (آخر رد :جاسر صفوان)       :: شركة الحمد وفروعها (آخر رد :soha mag)       :: دورة التأمــين البحــرى على البضــائع#دورات#تدريبية#معتمدة فى مجال التامينات (آخر رد :زينة محمد)       :: دورة الأحتيال في التأمين البحري#دورات#تدريبية#معتمدة فى مجال التامينات (آخر رد :زينة محمد)       :: دورة التميز والإبداع في التعامل مع المستفيدين من الخدمات التأمينية#ورشة فى عمل التامي (آخر رد :زينة محمد)       :: مهارات التسويق الحديثة للتأمين#دورات#تدريبية#معتمدة#التامينات#مركزالتدريب الدولي itr (آخر رد :زينة محمد)       :: دورة التأمين الطبى#دورات#تدريبية#معتمدة#التامينات#مركزالتدريب الدولي itr (آخر رد :زينة محمد)      
اختر لونك:
وَقُلِ اعْمَلُوا فَسَيَرَى اللَّهُ عَمَلَكُمْ وَرَسُولُهُ وَالْمُؤْمِنُونَ ۖ وَسَتُرَدُّونَ إِلَىٰ عَالِمِ الْغَيْبِ وَالشَّهَادَةِ فَيُنَبِّئُكُم بِمَا كُنتُمْ تَعْمَلُونَ [ التوبة : ( 105 )] كلمة الإدارة

يرجى إختيار القسم المناسب قبل النشر وسيعاقب المخالف بإنذار أول مرة وسيتم حظره إذا تكرر ذلك كلمة الإدارة

يُمنع كتابة مواضيع السحر والشعوذة والروحانيات والابراج بكافة الأشكال والمخالف سيعاقب بحظر مؤقت وإذا تكرر سيكون حظر دائم تنبيه هام جداً



أضف رد جديد
 
LinkBack أدوات الموضوع انواع عرض الموضوع

قديم 01-04-2019, 06:18 PM   #1
تاريخ التسجيل: Feb 2019
العمر: 38
المشاركات: 1,149
التقييم: 10
تاريخ التسجيل: Feb 2019
العمر: 38
المشاركات: 1,149
التقييم: 10
افتراضي كيفية استعمال مكتبة Redux في مشاريع React.js

يهتم المطورون بتنظيم تطبيقاتهم و إدارة العمليات ضمنها، خصوصاً إذا كان المشروع كبيراً وعليه تحمل ضغط المستخدمين مع كفاءة عالية في معالجة المعلومات المدخلة والمخرجة (Input/Output). لذلك ظهرت مكتبات عديدة تقوم بادارة الحالات (State Management) مثل Redux و mobX، والأولى هي موضوع درسنا هذا، لا لشيء إلا لأنها المكتبة الأشهر والأكثر استخداما
سأحاول في هذه المقالة شرح مكتبة Redux وتبسيطها بأحسن أسلوب ليفهمها الجميع، أغلب المبتدئين يخافون استعمالها و يرونها معقّدة أكثر من اللزوم، لذلك كان لا بد أولا أن نقوم بتقديم المكتبة بالشرح النظري ثم بعد ذلك نقوم بإنجاز مثال عملي لاستيعاب ما تعلمناه بشكل جيد.
الجزء النظري

كما تعلمون جاءت مكتبة React – والتي سبق لنا الحديث عنها في المدونة هنا – لحل إشكالية العلاقة بين واجهة المستخدم (User Interface) والبيانات (Data) التي تتغير بشكل مستمر في تطبيقات الويب. هذه المكتبة هي بالأساس مسؤولة عن إنشاء المشاهد (Views) في تطبيقات الويب وليست إطار عمل متكامل مثل أنجولار على سبيل المثال، ولهذا يتم تمثيلها عادة على أنها الحرف V في نظام MVC.
مكتبة React.js تعتمد نظام تدفق بيانات أحادي الإتجاه Unidirectional Data Flow، حيث أن المصدر الوحيد للحقيقة هو State، وبالتالي فكل تغيير يطرأ على حالة مكونات التطبيق يجب أن يمر أولا عبر تحديث هذا الكائن، ولهذا السبب أصلا سمي State أو حالة. وقد سبق لنا كتابة مقال خاص عن هذا الموضوع بيننا فيه وجه الإختلاف بين نظام Unidirectional Data Flow الذي تنتهجه React.js ونظام Bidirectional Data Flow الذي تعتمده جل أطر عمل جافاسكريبت الأخرى وعلى رأسها Angular.
لماذا استخدام مكتبة لإدارة الحالة ؟

قد نستطيع إنشاء تطبيقات كاملة بواسطة React.js ولكن سرعان ما سنكتشف محدودية خياراتنا خصوصا عندما تزداد درجة تعقيد التطبيق وتشابك العلاقات بين مختلف مكوناته (Components).
على سبيل المثال، لنفترض أنه لدينا مكون أب لديه ابن واحد، وهذا الأخير لديه حالته الخاصة. لاحظوا الصورة التالية :
كيفية استعمال مكتبة Redux مشاريع
عندما بدأنا بالعمل على مشروعنا لم يكن لدينا تصور كامل للشكل النهائي الذي ستكون عليه شجرة مكونات التطبيق (ومن الصعب في الحقيقة معرفة ذلك)، ظننا بأن المكون الأب في الصورة سيكون لديه ابن وحيد ولذلك أعطينا للأخير حالة خاصة به (state).
بعد مدة، أدركنا بأن الأب سيكون لديه أبناء آخرين يحتاجون للوصول إلى حالة الإبن الأول، وهذا مستحيل في React.js لأن الحالة يتم تمريرها من الأعلى للأسفل فقط عن طريق ال Props، ولا يمكن تمريرها أفقيا بين المكونات من نفس المستوى. إذن الحل الوحيد سيكون هو تجريد الإبن الأول من حالته (state) ورفعها إلى الأب ليقوم الأخير بإنزالها مرة أخرى للأبناء الثلاثة على شكل Prop
كيفية استعمال مكتبة Redux مشاريع
عمل مضني تتضاعف صعوبته مع ازدياد حجم المشروع وتشابك مكوناته.
فيبسوك كانت على بينة من هذه النقطة، لذلك قاموا بتصميم نمط جديد ليلعب دور Model، ولكن بالإعتماد على تدفق أحادي الإتجاه للبيانات (Unidirectional data flow) عوض التدفق ثنائي الإتجاه الذي ألفناه في أطر عمل مثل Angular. اسم هذا النمط هو FLUX وهناك مكتبة جافاسكريبت أيضا بنفس الإسم من فيسبوك لتمكين المطورين من الإستعانة بمميزات FLUX في مشاريعهم.
من مميزات نمط Flux أنه يقوم بجمع حالات (States) جميع المكونات وتخزينها في ما يعرف بالمخازن أو Stores. ويمكن لأي مكون (Component) الإتصال بتلك المخازن عن طريق آلية محددة لتحديث حالته ومن ثم الحصول على الحالة الجديدة على شكل Prop.
تعتبر مكتبة Redux من أشهر التطبيقات (Implementations) لنمط Flux، إلا أن لديها مميزاتها الخاصة، منها على سبيل المثال الإعتماد على مخزن واحد (Only One Store) للحالات عوض خاصية تعدد المخازن الموجودة في مكتبة Flux من فيسبوك.
كيفية استعمال مكتبة Redux مشاريع
يعود أول ظهور لمكتبة ريداكس إلى عام 2015 على يد المبرمجان Dan Abramov و Andrew Clark، وهي مكتبة مستقلة بذاتها ويمكن استخدامها في أي مشروع جافاسكريبت، وليس مشاريع React فقط.
كيف تعمل مكتبة Redux ؟

تُجمع المبادئ الأساسية ل Redux عادة في ثلاث جمل، وهي :
  1. مصدر واحد للحقيقة (Single source of truth): أي أنه يتم تخزين حالات التطبيق بالكامل في مخزن واحد فقط على شكل كائن جافاسكريبت.
  2. الحالة للقراءة فقط (State is read-only): تحصل المكونات على حالتها على شكل خصائص (Properties) قابلة للقراءة فقط، والطريقة الوحيدة لتحديثها وإجراء تغيير عليها هي عبر إرسال طلب (Dispatch action) يحمل عدد من المعلومات التي تمكن Redux من تحديد الحالة المراد تغييرها، وبعد ذلك إعادتها للمكون على شكل Prop كما قلنا في السابق. وكما نعلم جميعا، فإن ال Props في React.js قابلة للقراءة فقط ولا يمكن التعديل عليها.
  3. التغييرات تتم في وظائف نقية (Changes are made with pure functions): يتم تغيير الحالة في وظائف يفترض بها أن تكون نقية (Pure functions)، وتعرف هذه الوظائف في Redux باسم Reducers.
ولكي نفصل أكثر في طريقة وآلية عمل مدير الحالة Redux، سنحلل الصورة التالية :
كيفية استعمال مكتبة Redux مشاريع
يبدأ كل شيء من واجهة المستخدم (User Interface)، حيث يقوم المستخدم بسلوك معين يترجم في Redux إلى ما يعرف ب Action. هذا ال action يستقبل في دوال نقية (Pure functions) معروفة بال Reducers. تقبل في العادة معاملين اثنين : الحالة القديمة و ال action الذي تم إطلاقه في السابق، وتقوم بإرجاع (return) الحالة الجديدة بناءً على المعلومات الواردة في ال action. هذا الأخير عبارة عن كائن يضم خاصيتين أساسيتين :
  • type : هذه الخاصية إجبارية وتحتوي على نوع ال action المراد إجراؤه.
  • payload : هذه الخاصية غير إجبارية – ويمكن تسميتها أي اسم آخر غير payload – وتحتوي على المعلومات التي نريد إرسالها للمخزن (Store) ليتم دمجها في حالة التطبيق (State) عن طريق Reducers بطبيعة الحال.
// مثال لبنية الإجراء أو Action في Redux (أو نمط Flux بصفة عامة) : { type: 'ADD_TODO', payload: { text: 'Learn Redux...' } }
1
2
3
4
5
6
7

// مثال لبنية الإجراء أو Action في Redux (أو نمط Flux بصفة عامة) :
{
type: 'ADD_TODO',
payload: {
text: 'Learn Redux...'
}
}



الجزء التطبيقي

بعد أن شرحنا فكرة Redux نظرياً، سنشرح الفكرة تطبيقياً واخترت لكم مثالاً سهلاً مستعيناً به من مدونة daveceddia و هو تطبيق العداد أو Counter.
كيفية استعمال مكتبة Redux مشاريع
فكرته سهلة و بسيطة جداً..

لنلقي نظرة على الكود البرمجي:
import React from 'react'; class Counter extends React.Component { state = { count: 0 } increment = () => { this.setState({ count: this.state.count + 1 }); } decrement = () => { this.setState({ count: this.state.count - 1 }); } render() { return ( <div> <h2>Counter</h2> <div> <button onClick={this.decrement}>-</button> <span>{this.state.count}</span> <button onClick={this.increment}>+</button> </div> </div> ) } } export default Counter;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

import React from 'react';

class Counter extends React.Component {
state = { count: 0 }

increment = () => {
this.setState({
count: this.state.count + 1
});
}

decrement = () => {
this.setState({
count: this.state.count - 1
});
}

render() {
return (
<div>
<h2>Counter</h2>
<div>
<button onClick={this.decrement}>-</button>
<span>{this.state.count}</span>
<button onClick={this.increment}>+</button>
</div>
</div>
)
}
}

export default Counter;




كمراجعة سريعة، إليك ما قمنا به :
  • count عبارة عن حالة (state) مخزّنة ضمن المكوّن الرئيسي Counter.
  • عندما ينقر المستخدم على “+” فان onClick تستدعي الوظيفة increment و التي هي أيضا ضمن المكوّن الرئيسي Counter.
  • بعد ذلك تقوم الوظيفة increment بتحديث الحالة count و إضافة العدد 1، و هكذا دواليك.
  • بعد تحديث الحالة، يقوم رياكت أوتوماتيكيا بعمل إعادة عرض (Re-rendering) للمكوّن الرئيسي (Counter) ويتم إظهار قيمة العداد الجديدة.
  • نفس العمليات تتكرر عند كل نقرة على الزرين “+” أو “-“.
العمل بطريقة Redux

في مثل هذا النوع من المشاريع الصغيرة لا نحتاج للإستعانة بمدير للحالة مثل Redux، ولكن للغرض التعليمي لهذا المقال سنقوم بإعادة إنشاء نفس التطبيق بطريقة Redux حتى تتوضح وتترسخ جيدا في عقولنا كيفية عمله.
لنقم الآن بانشاء مشروع جديد بواسطة الحزمة create-react-app :
create-react-app counter-with-redux
1

create-react-app counter-with-redux



بعد إنشاء وتوليد المشروع، سنقوم بفتح الملف src/index.js ونعوض ما فيه بهذا الكود :
import React from 'react'; import { render } from 'react-dom'; import Counter from './Counter'; const App = () => ( <div> <Counter /> </div> ); render(<App />, document.getElementById('root'));
1
2
3
4
5
6
7
8
9
10
11

import React from 'react';
import { render } from 'react-dom';
import Counter from './Counter';

const App = () => (
<div>
<Counter />
</div>
);

render(<App />, document.getElementById('root'));



كما لا ننسى إنشاء الملف src/Counter.js ونضع فيه الكود الخاص بالمكون Counter الذي شرحناه سابقا.
بعدها نقوم بتنصيب مكتبتي Redux و react-redux.
$ yarn add Redux react-redux
1

$ yarn add Redux react-redux



react-redux هي الحزمة التي تمكن مكتبة Redux من العمل بكفاءة وتوافقية ممتازة مع مكتبة React.js.
نقوم بحذف الوظائف السابقة (increment و decrement) ونجعلها فارغة.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

import React from 'react';

class Counter extends React.Component {
increment = () => {
// fill in later
}

decrement = () => {
// fill in later
}

render() {
return (
<div>
<h2>Counter</h2>
<div>
<button onClick={this.decrement}>-</button>
<span>{this.props.count}</span>
<button onClick={this.increment}> </button>
</div>
</div>
)
}
}

export default Counter;



نلاحظ أننا غيّرنا الحالة this.state.count إلى خاصية this.props.count
إلى هنا، العداد لا يعرف شيئا عن خاصية بهذا الإسم.. المدير Redux هو من سيتولى توفير هذه الخاصية للمكون Counter.

للحصول على العدد من Redux سنحتاج الى استدعاء (connect):
import { connect } from 'react-redux';
1

import { connect } from 'react-redux';



نحتاج الآن الى الاتصال بالمكوّن (Counter) لربطه مع Redux عبر اضافة الكود التالي، و لا تهتم للاخطاء التي ستظهر كلها ستختفي بعد قليل.
// Add this function: function mapStateToProps(state) { return { count: state.count }; } // Then replace this: // export default Counter; // With this: export default connect(mapStateToProps)(Counter);
1
2
3
4
5
6
7
8
9
10
11
12

// Add this function:
function mapStateToProps(state) {
return {
count: state.count
};
}

// Then replace this:
// export default Counter;

// With this:
export default connect(mapStateToProps)(Counter);



الدالة mapStateToProps مهمة للغاية، فهي المكلفة بتحويل أجزاء من الحالة (state) إلى خصائص تمرَّر إلى المكونات المعنية (Counter في هذه الحالة) عن طريقة الدالة عالية الرتبة connect (تعرف كذلك ب Higher Order Function) والتي تقوم بإرجاع ما يعرف في React بمكون عالي الرتبة Higher Order Component أو HOC ليقوم بتمرير الحالة count إلى المكون الإبن Counter على شكل خاصية أو Prop.
تذكر الصورة أعلاه حيث الأبناء يرثون الحالة على شكل خصائص من الأب. الإبن هنا هو المكون Counter والأب هو المكون الغير المرئي الذي تقوم الدالة connect بإرجاعه. آمل أن يكون شرحي موفقا
بعد ما أكملنا الجزء الأول من تطبيقنا، لنعد الان لتعديل الملف الرئيسي للتطبيق: (src/index.js) و نستدعي المزوّد أو الممون (Provider) و الذي يعمل كمكون رئيسي يغطي جميع المكوّنات (Components) التي نحتاج ربطها مع Redux.
import { Provider } from 'react-redux'; ... const App = () => ( <Provider> <Counter/> </Provider> );
1
2
3
4
5
6
7
8
9

import { Provider } from 'react-redux';

...

const App = () => (
<Provider>
<Counter/>
</Provider>
);



الممون بحاجة لمعرفة المخزن الذي يأخد منه المعلومات التي يوفرها بدوره للمكونات الواقعة تحت نفوذه.
لننشئ هذا المخرن عبر الدالة createStore التي نستدعيها من مكتبة Redux كما يلي :
import { createStore } from 'redux'; const store = createStore(); const App = () => ( <Provider store={store}> <Counter/> </Provider> );
1
2
3
4
5
6
7
8
9

import { createStore } from 'redux';

const store = createStore();

const App = () => (
<Provider store={store}>
<Counter/>
</Provider>
);



لاحظوا بأننا قمنا بتمرير المخزن للممون على شكل خاصية اسمها store.
هل تتذكرون ال Reducers ؟

لدينا الآن الممون (Provider) ولدينا المخرن (Store) ولدينا واجهة المستخدم (UI). يتبقى لنا أن نقوم بإنشاء وظيفة Reducer واحدة على الأقل لكي نتمكن من تمرير الحالة للمخرن الذي قمنا بتعريفه.
ال Reducer هو مجرد دالة جافاسكريبت عادية تقبل معاملين اثنين : الحالة الآنية (Current state)، والإجراء المتخذ (Action)، بينما تقوم بإرجاع كائن يمثل حالة التطبيق الجديدة (New state).
لنقم بتعريف هذه الدالة ونمررها كمعامل للمخرن الذي أنشأناه قبل هنيهة :
import { createStore } from 'redux'; function counterReducer(state = {count: 0}, action) { return state; } const store = createStore(counterReducer); const App = () => ( <Provider store={store}> <Counter/> </Provider> );
1
2
3
4
5
6
7
8
9
10
11
12
13

import { createStore } from 'redux';

function counterReducer(state = {count: 0}, action) {
return state;
}

const store = createStore(counterReducer);

const App = () => (
<Provider store={store}>
<Counter/>
</Provider>
);



نلاحظ أننا قمنا بإعطاء قيمة افتراضية للكائن state حيث count يساوي 0. وبما أننا لم نقم بعد بأي إجراء داخل ال Reducer فإننا نقوم بإرجاع الحالة الإفتراضية نفسها.
سنقوم بإجراء تعديلات على دالة counterReducer حتى تأخذ بعين الإعتبار الإجراءات التي ستتوصل بها، وهي في مثالنا البسيط هذا إجراءين اثنين لا ثالث لهما : INCREMENT و DECREMENT.
نتذكر جميعا عندما تحدثنا عن بنية ال actions، حيث أنها عبارة عن كائنات تضم خاصية واحد إجبارية هي type وخاصيات أخرى اختيارية لتمرير عدد من البيانات إلى ال Reducer.
في تطبيق العداد لا نريد تمرير أي معلومة لهذا ال Reducer، فكلما نسعى إليه هو إضافة أو طرح العدد 1 بحسب نوع (Type) الإجراء (INCREMENT أو DECREMENT).
إذن الإجراء (action) سيكون على هذه الهيئة البسيطة :
{ type: "INCREMENT" }
1
2
3

{
type: "INCREMENT"
}



لنعد الآن إلى دالتنا counterReducer ونستثمر فيها ما تعلمناه :
function counterReducer(state = {count: 0}, action) { switch(action.type) { case 'INCREMENT': return { count: state.count + 1 }; case 'DECREMENT': return { count: state.count - 1 }; default: return state; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14

function counterReducer(state = {count: 0}, action) {
switch(action.type) {
case 'INCREMENT':
return {
count: state.count + 1
};
case 'DECREMENT':
return {
count: state.count - 1
};
default:
return state;
}
}



يجب الإنتباه إلى أنه يجب على ال Reducer إرجاع حالة جديدة حتى ولو لم يتم اتخاذ أي إجراء بداخله، ولذلك نقوم دائما بإرجاع الحالة الإفتراضية في منطقة default وإلا فإن قيمة الحالة ستكون undefined.
ملاحظة مهمة : State is immutable

تتبع مكتبة Redux نمط ومبادئ البرمجة الوظيفية في جافاسكريبت، ومن أهم تجلياتها أن الكائن state غير قابل للتغيير بصفة مباشرة (Immutable). هذا المبدأ معروف في functional programming باسم Immutability.
هذا يعني أنه لا يمكننا كتابة أكواد كهذه :
function badCounterReducer(state = {count: 0}, action) { switch(action.type) { case 'INCREMENT': // NO! BAD: this is changing state! state.count++; return state; case 'DECREMENT': // NO! BAD: this is changing state too! state.count--; return state; default: // this is fine. return state; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

function badCounterReducer(state = {count: 0}, action) {
switch(action.type) {
case 'INCREMENT':
// NO! BAD: this is changing state!
state.count++;
return state;

case 'DECREMENT':
// NO! BAD: this is changing state too!
state.count--;
return state;

default:
// this is fine.
return state;
}
}



لا يمكن كذلك استخدام وظائف المصفوفات مثل push لأنها تقوم بتغيير المصفوفة عوضا عن إنشاء مصفوفة جديدة كما تفعل الوظيفة concat مثلا، وبالتالي ينصح دائما باستخدام الأخيرة في مثل هذه الحالات حتى نظل محافظين على مبدأ الغير قابلية للتغيير أو Immutability.
على كل حال، موضوع Immutability يحتاج شرحا موسعا ومقالا خاصا، ننجزه في قادم الأيام إن شاء الله
لحظة من فضلك : من أين جاءت هذه الإجراءات ؟

قد تسأل نفسك وأنت تقرأ الدرس: من أين جاءت هذه ال actions ؟ وكيف وصلت لدالة counterReducer ؟
إذا سألت هذا السؤال فأهنئك على تركيزك العالي، فطرح الأسئلة الجيدة هي أولى وأهم مراحل التعلم.
ببساطة الإجراء ات يتم إطلاقها من داخل مكونات React عن طريق الوظيفة disptach التي يوفرها Redux، وهي في الأصل وظيفة خاصة بالمخزن أو Store يمكن استدعاؤها على النحو التالي :
store.dispatch(someAction)
1

store.dispatch(someAction)



ولكن الدالة connect التي تمنحها الحزمة react-redux، جعلت مهمة إطلاق الإجراءات أكثر عملية وملاءمة لبيئة React.js، حيث أنها توفر الوظيفة disptach كخاصية (prop) للمكون، تماما كما تحول state إلى props خاصة بالمكون مثلما رأينا في فقرة سابقة.
هكذا سيصبح شكل المكون Counter الجديد على هذا النحو :
import React from 'react'; import { connect } from 'react-redux'; class Counter extends React.Component { increment = () => { this.props.dispatch({ type: 'INCREMENT' }); } decrement = () => { this.props.dispatch({ type: 'DECREMENT' }); } render() { return ( <div> <h2>Counter</h2> <div> <button onClick={this.decrement}>-</button> <span>{this.props.count}</span> <button onClick={this.increment}>+</button> </div> </div> ) } } function mapStateToProps(state) { return { count: state.count }; } export default connect(mapStateToProps)(Counter);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

import React from 'react';
import { connect } from 'react-redux';

class Counter extends React.Component {
increment = () => {
this.props.dispatch({ type: 'INCREMENT' });
}

decrement = () => {
this.props.dispatch({ type: 'DECREMENT' });
}

render() {
return (
<div>
<h2>Counter</h2>
<div>
<button onClick={this.decrement}>-</button>
<span>{this.props.count}</span>
<button onClick={this.increment}>+</button>
</div>
</div>
)
}
}

function mapStateToProps(state) {
return {
count: state.count
};
}

export default connect(mapStateToProps)(Counter);



النهاية

هكذا نكون قد أنهينا هذا الدرس الذي يمثل مدخلا لفهم عميق وجيد لمكتبة Redux وآلية عملها.
هناك جزئيات وتفاصيل عديدة لم نتطرق إليها حتى لا يطول الدرس أكثر مما هو طويل الآن وحتى لا يستشكل فهمه على المبتدئين الذين نولي لهم دائما أهمية قصوى في مدونة توتومينا.

raheel غير متواجد حالياً   اقتباس
أضف رد جديد


الذين يشاهدون محتوى الموضوع الآن : 1 ( الأعضاء 0 والزوار 1)
 

تعليمات المشاركة
لا تستطيع إضافة مواضيع جديدة
لا تستطيع الرد على المواضيع
لا تستطيع إرفاق ملفات
لا تستطيع تعديل مشاركاتك

BB code is متاحة
كود [IMG] متاحة
كود HTML معطلة
Trackbacks are متاحة
Pingbacks are متاحة
Refbacks are متاحة


المواضيع المتشابهه
الموضوع كاتب الموضوع المنتدى مشاركات آخر مشاركة
كل شء عن أطر العمل Angular ،React.js و Vue.js raheel قسم تطوير المواقع ومحركات البحث والسيو Seo والووردبريس WordPress 0 10-04-2019 08:34 PM
كيفية تنسيق المكونات في React.js raheel قسم تطوير المواقع ومحركات البحث والسيو Seo والووردبريس WordPress 0 01-04-2019 06:05 PM
كيفية إعداد مشروع React.js باستخدام Webpack 4 و Babel raheel قسم تطوير المواقع ومحركات البحث والسيو Seo والووردبريس WordPress 0 01-04-2019 06:04 PM
تعرف علي الكتب الممتازة التي تساعدك علي تعلم React.js في 2019 raheel قسم تطوير المواقع ومحركات البحث والسيو Seo والووردبريس WordPress 0 01-04-2019 05:27 PM
كيفية استغلال وقت الفراغ رفيق الدرب المواضيع العامة 0 07-02-2019 03:39 AM


الساعة الآن 10:43 PM

 


Content Relevant URLs by vBSEO ©2010, Crawlability, Inc.