Redux مقابل React Context API



في React 16.3 ، تمت إضافة واجهة برمجة تطبيقات سياق جديدة. الجديد بمعنى أن واجهة برمجة تطبيقات Context API القديمة كانت خلف الكواليس ، ومعظم الناس إما لم يعرفوا بوجودها أو لم يستخدموها ، لأن الوثائق نصحت بتجنب استخدامها.

ومع ذلك ، تعد الآن واجهة برمجة تطبيقات Context API جزءًا كاملًا من React ، وهي مفتوحة للاستخدام (وليس كما كان من قبل ، رسميًا).

مباشرة بعد إصدار React 16.3 ، ظهرت مقالات تعلن وفاة Redux بسبب واجهة برمجة التطبيقات الجديدة Context API. إذا كنت قد سألت Redux عن هذا ، أعتقد أنه كان سيجيب - "تقارير موتي مبالغ فيها إلى حد كبير ."

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

إذا كنت ترغب فقط في إلقاء نظرة عامة على واجهة برمجة تطبيقات Context API ، فيمكنك اتباع الرابط .

مثال على تطبيق رد الفعل


سأقترح أن يكون لديك فهم لمبادئ العمل مع الحالة في React (الدعائم والحالة) ، ولكن إذا لم يكن كذلك ، فلدي دورة تدريبية مجانية لمدة 5 أيام لمساعدتك في التعرف عليها .

دعونا نلقي نظرة على مثال ينقلنا إلى المفهوم المستخدم في Redux. سنبدأ بإصدار بسيط من React ، ثم نرى كيف يبدو في Redux وأخيرًا مع السياق.



في هذا التطبيق ، يتم عرض معلومات المستخدم في مكانين: في شريط التنقل في الزاوية العلوية اليمنى وفي اللوحة الجانبية بجوار المحتوى الرئيسي.

(قد تلاحظ أن هناك الكثير من أوجه التشابه مع Twitter. ليس من قبيل المصادفة! إحدى أفضل الطرق لصقل مهارات رد الفعل لديك هي النسخ (إنشاء نسخ متماثلة من المواقع / التطبيقات الحالية) .

يبدو هيكل المكون كما يلي:



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

بعد ذلك ، من أجل نقل معلومات حول المستخدم إلى تلك المكونات التي تحتاج إليها ، يجب على التطبيق تمريرها إلى Nav and Body. هم ، بدورهم ، سيمررونه إلى UserAvatar (مرحى!) والشريط الجانبي. أخيرًا ، يجب أن يمرره الشريط الجانبي إلى UserStats.

دعنا نرى كيف يعمل هذا في التعليمات البرمجية (أضع كل شيء في ملف واحد لتسهيل قراءته ، ولكن في الواقع سيتم تقسيمه إلى ملفات منفصلة ، باتباع بعض الهيكل القياسي ).

import React from "react"; import ReactDOM from "react-dom"; import "./styles.css"; const UserAvatar = ({ user, size }) => ( <img className={`user-avatar ${size || ""}`} alt="user avatar" src={user.avatar} /> ); const UserStats = ({ user }) => ( <div className="user-stats"> <div> <UserAvatar user={user} /> {user.name} </div> <div className="stats"> <div>{user.followers} Followers</div> <div>Following {user.following}</div> </div> </div> ); const Nav = ({ user }) => ( <div className="nav"> <UserAvatar user={user} size="small" /> </div> ); const Content = () => <div className="content">main content here</div>; const Sidebar = ({ user }) => ( <div className="sidebar"> <UserStats user={user} /> </div> ); const Body = ({ user }) => ( <div className="body"> <Sidebar user={user} /> <Content user={user} /> </div> ); class App extends React.Component { state = { user: { avatar: "https://www.gravatar.com/avatar/5c3dd2d257ff0e14dbd2583485dbd44b", name: "Dave", followers: 1234, following: 123 } }; render() { const { user } = this.state; return ( <div className="app"> <Nav user={user} /> <Body user={user} /> </div> ); } } ReactDOM.render(<App />, document.querySelector("#root")); 


CodeSandbox نموذج التعليمات البرمجية

يقوم التطبيق هنا بتهيئة الحالة التي تحتوي على كائن المستخدم. في تطبيق حقيقي ، من المرجح أن تقوم باستخراج هذه البيانات من الخادم وحفظها في حالة العرض.

فيما يتعلق بالدعائم ("دعامة الحفر") ، إنها ليست مشكلة كبيرة . إنه يعمل بشكل رائع. رمي الدعائم ، هذا مثال مثالي على رد الفعل. لكن القذف في أعماق شجرة الولاية يمكن أن يكون مزعجًا بعض الشيء عند الكتابة. ومزعج أكثر إذا كان عليك إرسال الكثير من الدعائم (وليس واحدة).

ومع ذلك ، هناك نقص كبير في هذه الإستراتيجية: فهي تخلق اتصالًا بين المكونات التي لا يجب توصيلها. في المثال أعلاه ، يجب أن يقبل Nav دعامة "المستخدم" ويمررها إلى UserAvatar ، حتى إذا لم يكن Nav بحاجة إليها.

من الصعب إعادة استخدام المكونات المقترنة بشكل وثيق (مثل تلك التي تمرر الدعائم لأطفالها) ، حيث يتعين عليك ربطها بآباء جدد كلما استخدمتها في مكان جديد.

دعونا نرى كيف يمكننا تحسين هذا.

قبل استخدام السياق أو Redux ...


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

في هذا المثال ، تعد دعائم الأطفال حلاً رائعًا للمكونات التي يجب أن تكون عالمية ، مثل Nav ، و Sidebar ، و Body. انتبه أيضًا إلى أنه يمكنك تمرير JSX إلى أي دعامة ، وليس للأطفال فقط - لذلك ، إذا كنت بحاجة إلى أكثر من "فتحة" واحدة لتوصيل المكونات ، فتذكر ذلك.

في ما يلي مثال على تطبيق React الذي يقوم فيه Nav و Body و Sidebar بأخذ الأطفال وعرضهم كما هم. وبالتالي ، لا يحتاج الشخص الذي يستخدم المكون إلى القلق بشأن نقل بيانات معينة يتطلبها المكون. يمكنه ببساطة عرض ما يحتاجه في المكان ، باستخدام البيانات الموجودة لديه بالفعل في النطاق. يوضح هذا المثال أيضًا كيفية استخدام أي دعامة لنقل الأطفال.

(شكرا لدان أبراموف على هذا العرض !)

 import React from "react"; import ReactDOM from "react-dom"; import "./styles.css"; const UserAvatar = ({ user, size }) => ( <img className={`user-avatar ${size || ""}`} alt="user avatar" src={user.avatar} /> ); const UserStats = ({ user }) => ( <div className="user-stats"> <div> <UserAvatar user={user} /> {user.name} </div> <div className="stats"> <div>{user.followers} Followers</div> <div>Following {user.following}</div> </div> </div> ); //  children   . const Nav = ({ children }) => ( <div className="nav"> {children} </div> ); const Content = () => ( <div className="content">main content here</div> ); const Sidebar = ({ children }) => ( <div className="sidebar"> {children} </div> ); // Body   sidebar  content,    , //    . const Body = ({ sidebar, content }) => ( <div className="body"> <Sidebar>{sidebar}</Sidebar> {content} </div> ); class App extends React.Component { state = { user: { avatar: "https://www.gravatar.com/avatar/5c3dd2d257ff0e14dbd2583485dbd44b", name: "Dave", followers: 1234, following: 123 } }; render() { const { user } = this.state; return ( <div className="app"> <Nav> <UserAvatar user={user} size="small" /> </Nav> <Body sidebar={<UserStats user={user} />} content={<Content />} /> </div> ); } } ReactDOM.render(<App />, document.querySelector("#root")); 


CodeSandbox نموذج التعليمات البرمجية

إذا كان تطبيقك معقدًا للغاية (أكثر تعقيدًا من هذا المثال!) ، فقد يكون من الصعب فهم كيفية تكييف القالب مع الأطفال. دعونا نرى كيف يمكنك استبدال إعادة توجيه الدعائم بـ Redux.

مثال Redux


سألقي نظرة سريعة على مثال Redux حتى نتمكن من فهم كيفية عمل السياق بشكل أفضل ، لذلك إذا لم يكن لديك فهم واضح لـ Redux ، اقرأ أولاً مقدمة عن Redux (أو شاهد الفيديو ).

هنا تم إعادة تصميم تطبيق React الخاص بنا لاستخدام Redux. تم نقل معلومات المستخدم إلى متجر Redux ، مما يعني أنه يمكننا استخدام وظيفة توصيل رد الفعل المتفاعل لتمرير دعامة المستخدم مباشرة إلى المكونات التي تحتاجها.

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

المخفض لا يفعل الكثير هنا ؛ انها بسيطة جدا. لدي شيء آخر حول كيفية عمل مخفضات Redux وكيفية كتابة الشفرة الثابتة التي يستخدمونها.

 import React from "react"; import ReactDOM from "react-dom"; //    createStore, connect, and Provider: import { createStore } from "redux"; import { connect, Provider } from "react-redux"; //  reducer       . const initialState = {}; function reducer(state = initialState, action) { switch (action.type) { //    action SET_USER  state. case "SET_USER": return { ...state, user: action.user }; default: return state; } } //  store  reducer'   . const store = createStore(reducer); // Dispatch' action     user. store.dispatch({ type: "SET_USER", user: { avatar: "https://www.gravatar.com/avatar/5c3dd2d257ff0e14dbd2583485dbd44b", name: "Dave", followers: 1234, following: 123 } }); //   mapStateToProps,      state (user) //     `user` prop. const mapStateToProps = state => ({ user: state.user }); //  UserAvatar    connect(),    //`user` ,      . //     2 : // const UserAvatarAtom = ({ user, size }) => ( ... ) // const UserAvatar = connect(mapStateToProps)(UserAvatarAtom); const UserAvatar = connect(mapStateToProps)(({ user, size }) => ( <img className={`user-avatar ${size || ""}`} alt="user avatar" src={user.avatar} /> )); //   UserStats    connect(),    // `user` . const UserStats = connect(mapStateToProps)(({ user }) => ( <div className="user-stats"> <div> <UserAvatar /> {user.name} </div> <div className="stats"> <div>{user.followers} Followers</div> <div>Following {user.following}</div> </div> </div> )); //    Nav      `user`. const Nav = () => ( <div className="nav"> <UserAvatar size="small" /> </div> ); const Content = () => ( <div className="content">main content here</div> ); //   Sidebar. const Sidebar = () => ( <div className="sidebar"> <UserStats /> </div> ); //   Body. const Body = () => ( <div className="body"> <Sidebar /> <Content /> </div> ); //  App    ,     . const App = () => ( <div className="app"> <Nav /> <Body /> </div> ); //     Provider, //   connect()    store. ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.querySelector("#root") ); 


CodeSandbox نموذج التعليمات البرمجية

ربما تتساءل الآن عن كيفية تحقيق Redux لهذا السحر. مذهل كيف لا يدعم React تمرير الدعائم إلى مستويات متعددة ، وهل يمكن لـ Redux القيام بذلك؟

الجواب هو أن Redux يستخدم وظيفة السياق React (ميزة السياق). ليست واجهة برمجة تطبيقات Context API الحديثة (ليس بعد) ، ولكن واجهة برمجة التطبيقات القديمة. واحد تقول وثائق React لا تستخدمه إلا إذا كنت تكتب مكتبتك الخاصة أو تعرف ما تفعله.

يشبه السياق ناقل كمبيوتر يتبع كل مكون: للحصول على الطاقة (البيانات) التي تمر من خلاله ، ما عليك سوى الاتصال. وربط رد فعل رد فعل ذلك بالضبط.

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

connect هي وظيفة خالصة

يؤدي الاتصال تلقائيًا إلى جعل المكونات المتصلة "نظيفة" ، أي أنه سيتم إعادة تقديمها فقط عندما تتغير دعائمها - أي عندما تتغير شريحة حالة Redux الخاصة بها. هذا يمنع إعادة العرض غير الضرورية ويسرع التطبيق.

تصحيح الأخطاء بسهولة مع Redux

يتم موازنة حفل كتابة الإجراءات والمخفضات بسهولة مذهلة في تصحيح الأخطاء التي يمنحكها Redux.

مع ملحق Redux DevTools ، تحصل على سجل تلقائي لجميع الإجراءات التي يقوم بها تطبيقك. في أي وقت ، يمكنك فتحه ومعرفة الإجراءات التي تم إطلاقها ، وما هي حمولتها ، والحالة قبل الإجراء وبعده.



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

هناك أيضًا أدوات مثل LogRocket ، والتي تمنحك بشكل أساسي Redux DevTools الدائم في الإنتاج لكل من المستخدمين. حصلت على تقرير خطأ؟ لا مشكلة. انظر إلى جلسة المستخدم هذه في LogRocket ، ويمكنك رؤية تكرار ما فعله والإجراءات التي تم إطلاقها. كل هذا يعمل باستخدام دفق العمل Redux.

توسيع Redux مع الوسيطة

يدعم Redux مفهوم البرامج الوسيطة (كلمة فاخرة لـ "وظيفة يتم تشغيلها في كل مرة يتم فيها إرسال إجراء"). كتابة الوسيطة الخاصة بك ليست صعبة كما قد تبدو ، وتسمح لك باستخدام بعض الأدوات القوية.

على سبيل المثال ...

  • هل تريد إرسال طلب واجهة برمجة التطبيقات في كل مرة يبدأ فيها اسم الإجراء بـ FETCH_؟ يمكنك القيام بذلك باستخدام الوسيطة.
  • هل تريد مكانًا مركزيًا لتسجيل الأحداث في برنامج التحليل الخاص بك؟ الوسيطة هي مكان جيد للقيام بذلك.
  • هل تريد منع إجراء ما من البدء في نقطة زمنية محددة؟ يمكنك القيام بذلك باستخدام الوسيطة ، غير مرئية لبقية التطبيق الخاص بك.
  • هل تريد اعتراض إجراء له رمز JWT وحفظه تلقائيًا في التخزين المحلي؟ نعم ، الوسيطة.

هنا مقال جيد مع أمثلة لكيفية كتابة الوسيطة Redux.

كيفية استخدام واجهة برمجة تطبيقات React Context API


ولكن ربما لا تحتاج إلى كل هذه الشذوذات Redux. قد لا تحتاج إلى تصحيح أخطاء أو ضبط أو تحسينات تلقائية بسيطة في الأداء - كل ما تريد القيام به هو نقل البيانات بسهولة. ربما يكون تطبيقك صغيرًا ، أو تحتاج فقط إلى القيام بشيء سريع والتعامل مع التفاصيل الدقيقة لاحقًا.

ربما تكون واجهة برمجة تطبيقات Context API الجديدة مناسبة لك. دعونا نرى كيف يعمل.

لقد نشرت برنامجًا تعليميًا سريعًا لواجهة برمجة تطبيقات السياق على Egghead إذا كنت تفضل المشاهدة بدلاً من القراءة (3:43).

فيما يلي 3 مكونات مهمة لواجهة برمجة تطبيقات السياق:

  • دالة React.createContext التي تنشئ السياق
  • الموفر (يقوم بإرجاع createContext) ، الذي يقوم بإعداد "الناقل" ،
    يمر عبر شجرة المكون
  • المستهلك (تم إرجاع createContext أيضًا) الذي ينغمس فيه
    "ناقل كهربائي" لاستخراج البيانات

الموفر مشابه جدًا للموفر في React-Redux. يأخذ قيمة يمكن أن تكون أي شيء تريده (يمكن أن يكون حتى متجر Redux ... ولكن هذا سيكون غبيًا). على الأرجح ، هذا كائن يحتوي على بياناتك وأي إجراءات تريد تنفيذها مع البيانات.

يعمل المستهلك قليلاً مثل وظيفة الاتصال في React-Redux ، حيث يتصل بالبيانات ويجعلها متاحة لمكون يستخدمها.

فيما يلي النقاط البارزة:

 //     context //    2 : { Provider, Consumer } // ,   ,  UpperCase,  camelCase //  ,          , //        . const UserContext = React.createContext(); // ,     context, //   Consumer. // Consumer   "render props". const UserAvatar = ({ size }) => ( <UserContext.Consumer> {user => ( <img className={`user-avatar ${size || ""}`} alt="user avatar" src={user.avatar} /> )} </UserContext.Consumer> ); // ,      "user prop", //   Consumer    context. const UserStats = () => ( <UserContext.Consumer> {user => ( <div className="user-stats"> <div> <UserAvatar user={user} /> {user.name} </div> <div className="stats"> <div>{user.followers} Followers</div> <div>Following {user.following}</div> </div> </div> )} </UserContext.Consumer> ); // ...    ... // ... (      `user`). //  App   context ,  Provider. class App extends React.Component { state = { user: { avatar: "https://www.gravatar.com/avatar/5c3dd2d257ff0e14dbd2583485dbd44b", name: "Dave", followers: 1234, following: 123 } }; render() { return ( <div className="app"> <UserContext.Provider value={this.state.user}> <Nav /> <Body /> </UserContext.Provider> </div> ); } } 


CodeSandbox نموذج التعليمات البرمجية

دعونا نلقي نظرة على كيفية عملها.

تذكر ، لدينا 3 أجزاء: السياق نفسه (تم إنشاؤه باستخدام React.createContext) ومكونين يتفاعلان معه (الموفر والمستهلك).

يعمل الموفر والمستهلك معًا

الموفر والمستهلك مرتبطان ولا ينفصلان. إنهم يعرفون فقط كيفية التفاعل مع بعضهم البعض. إذا قمت بإنشاء سياقين منفصلين ، على سبيل المثال ، "Context1" و "Context2" ، فلن يكون بمقدور موفر السياق والمستهلك 1 التواصل مع سياق الموفر والمستهلك 2.

لا يحتوي السياق على حالة

لاحظ أن السياق ليس له حالة خاصة به . هذه مجرد قناة لبياناتك. يجب عليك تمرير القيمة إلى الموفر ، وسيتم تمرير هذه القيمة إلى أي مستهلك يعرف كيفية البحث عنها (الموفر مرتبط بنفس السياق مثل المستهلك).

عند إنشاء سياق ، يمكنك تمرير "الافتراضي" على النحو التالي:

 const Ctx = React.createContext(yourDefaultValue); 


القيمة الافتراضية هي ما سيحصل عليه المستهلك عندما يتم وضعه في الشجرة دون أن يقوم الموفر فوقه. إذا لم تقم بتمريرها ، فلن يتم تحديد القيمة. لاحظ أن هذه هي القيمة الافتراضية ، وليست القيمة الأولية . السياق لا يحفظ أي شيء ؛ ينشر البيانات التي تمررها إليه.

يستخدم المستهلك نمط الدعائم تقديم

تعتبر وظيفة connect Redux مكون ترتيب أعلى (يُختصر باسم HoC). يلف مكونًا آخر ويمرر الدعائم إليه.

على النقيض من ذلك ، يتوقع المستهلك أن يكون المكون الفرعي دالة. ثم تستدعي هذه الوظيفة أثناء العرض ، لتمرير القيمة التي تلقتها من الموفر في مكان ما فوقها (إما القيمة الافتراضية من السياق ، أو غير محددة إذا لم تقم بتمرير القيمة الافتراضية).

يأخذ الموفر قيمة واحدة.

قيمة واحدة فقط ، مثل الدعامة. لكن تذكر أن القيمة يمكن أن تكون أي شيء. من الناحية العملية ، إذا كنت ترغب في تمرير قيم متعددة لأسفل ، يجب عليك إنشاء كائن بكل القيم وتمرير هذا الكائن لأسفل.

مرونة سياق API


نظرًا لأن إنشاء السياق يمنحنا مكونين للعمل مع (المزود والمستهلك) ، يمكننا استخدامها كما نريد. هنا زوج من الأفكار.

التفاف المستهلك في HOC

لا تعجبك فكرة إضافة UserContext.Consumer حول كل مكان يحتاج إليها؟ هذا هو رمزك! لديك الحق في أن تقرر ما سيكون خيارك الأفضل.

إذا كنت تفضل الحصول على القيمة كدعم ، يمكنك كتابة غلاف صغير حول المستهلك على النحو التالي:

 function withUser(Component) { return function ConnectedComponent(props) { return ( <UserContext.Consumer> {user => <Component {...props} user={user}/>} </UserContext.Consumer> ); } } 

بعد ذلك ، يمكنك إعادة كتابة UserAvatar ، على سبيل المثال ، باستخدام وظيفة withUser:

 const UserAvatar = withUser(({ size, user }) => ( <img className={`user-avatar ${size || ""}`} alt="user avatar" src={user.avatar} /> )); 

وفويلا ، يمكن أن يعمل السياق تمامًا مثل ربط Redux. ناقص النظافة التلقائية.

هنا مثال من CodeSandbox مع هذا HOC .

إبقاء الدولة في مزود

تذكر أن المزود مجرد قناة. لا يحفظ أي بيانات. ولكن هذا لا يمنعك من إنشاء غلافك الخاص لتخزين البيانات.

في المثال أعلاه ، يتم تخزين البيانات في التطبيق ، لذا كان الشيء الوحيد الذي كنت بحاجة لفهمه هو موفر + مكونات المستهلك. ولكن ربما تريد إنشاء متجرك الخاص. يمكنك إنشاء مكون لتخزين الحالة وتمريرها عبر السياق:

 class UserStore extends React.Component { state = { user: { avatar: "https://www.gravatar.com/avatar/5c3dd2d257ff0e14dbd2583485dbd44b", name: "Dave", followers: 1234, following: 123 } }; render() { return ( <UserContext.Provider value={this.state.user}> {this.props.children} </UserContext.Provider> ); } } // ...    ... const App = () => ( <div className="app"> <Nav /> <Body /> </div> ); ReactDOM.render( <UserStore> <App /> </UserStore>, document.querySelector("#root") ); 

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

هنا مثال CodeSandbox مع UserStore هذا.

رمي الإجراءات لأسفل من خلال السياق

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

إليك مثال جديد: غرفة بسيطة بها مفتاح لتبديل لون الخلفية - أوه ، أعني الضوء.



يتم تخزين الحالة في المتجر ، والتي تحتوي أيضًا على وظيفة تبديل الضوء. يتم تمرير كل من الحالة والوظيفة من خلال السياق.

 import React from "react"; import ReactDOM from "react-dom"; import "./styles.css"; //  context. const RoomContext = React.createContext(); // ,     //   . class RoomStore extends React.Component { state = { isLit: false }; toggleLight = () => { this.setState(state => ({ isLit: !state.isLit })); }; render() { //  state  onToggleLight action return ( <RoomContext.Provider value={{ isLit: this.state.isLit, onToggleLight: this.toggleLight }} > {this.props.children} </RoomContext.Provider> ); } } //    ,    , //       RoomContext. const Room = () => ( <RoomContext.Consumer> {({ isLit, onToggleLight }) => ( <div className={`room ${isLit ? "lit" : "dark"}`}> The room is {isLit ? "lit" : "dark"}. <br /> <button onClick={onToggleLight}>Flip</button> </div> )} </RoomContext.Consumer> ); const App = () => ( <div className="app"> <Room /> </div> ); //     RoomStore, //           . ReactDOM.render( <RoomStore> <App /> </RoomStore>, document.querySelector("#root") ); 

هنا مثال عمل كامل في CodeSandbox .

بعد كل شيء ، ما الذي يجب استخدامه ، سياق أو إعادة؟

الآن بعد أن رأيت المسارين ، أيهما يستحق استخدامه؟ أعلم أنك تريد فقط سماع إجابة هذا السؤال ، لكن يجب أن أجيب - "هذا يعتمد عليك".

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

خطأ فادح يتخلل نظام جافا سكريبت بأكمله هو فكرة المنافسة . هناك فكرة أن كل خيار هو لعبة محصلتها صفر: إذا كنت تستخدم المكتبة A ، فلا يجب عليك استخدام مكتبة منافس B. وهي أنه عندما تظهر مكتبة جديدة أفضل من المكتبة السابقة ، فيجب أن تزاحم المكتبة الحالية. يجب أن يكون كل شيء إما / أو أنه يجب عليك إما اختيار الأحدث والأفضل ، أو أن تنزل إلى الخلفية مع مطورين من الماضي.

أفضل طريقة هي النظر إلى هذا الاختيار الرائع بمثال ، مجموعة من الأدوات. إنه مثل الاختيار بين استخدام مفك أو مفك قوي. في 80٪ من الحالات ، سيقوم مفك البراغي بهذه المهمة بشكل أسهل وأسرع من مفك البراغي. ولكن بالنسبة لـ 20 ٪ الأخرى ، سيكون مفك البراغي هو الخيار الأفضل (لا توجد مساحة كافية ، أو أن العنصر رقيق). عندما اشتريت مفكًا ، لم أرميه على الفور ، ولم يقم باستبداله ، ولكن ببساطة أعطاني خيارًا آخر. طريقة أخرى لحل المشكلة.

السياق "لا يستبدل" Redux ، ولا يزيد عن رد فعل "يستبدل" Angular أو jQuery. الجحيم ، ما زلت أستخدم jQuery عندما أحتاج إلى القيام بشيء بسرعة. ما زلت أستخدم أحيانًا قوالب EJS من جانب الخادم بدلاً من نشر تطبيق React. في بعض الأحيان يكون رد الفعل أكثر مما تحتاج إليه لإكمال المهمة. وينطبق الشيء نفسه على Redux.

اليوم ، إذا كان Redux أكثر مما تحتاج ، يمكنك استخدام السياق.

يمكن أن يكون رد فعل التعلم صعبًا - فهناك العديد من المكتبات والأدوات!

نصيحتي تجاهل كل منهم :)

لتعليمات خطوة قراءة كتابي «الصرفة في رد فعل» .

Source: https://habr.com/ru/post/ar419449/


All Articles