استخدام وظيفة connect () من رد الفعل المتفاعل

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

الصورة

حول إدارة الدولة في تطبيقات JavaScript


يزود React المطور بآليتين رئيسيتين لنقل البيانات إلى المكونات. هذه هي الخصائص (الدعائم) والدولة. الخصائص للقراءة فقط وتسمح للمكونات الرئيسية بتمرير السمات للمكونات الفرعية. الحالة هي كيان محلي مغلف داخل مكون يمكن أن يتغير في أي وقت في دورة حياة المكون.

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

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

إليك كيفية إنشاء مستودعات Redux:

import { createStore } from 'redux'; const initialState = {    auth: { loggedIn: false } } const store = createStore((state = initialState, action) => {    switch (action.type) {        case "LOG_IN":            return { ...state, auth: { loggedIn: true } };            break;        case "LOG_OUT":            return { ...state, auth: { loggedIn: false } };            break;        default:            return state;            break;    }    }) 

رد فعل حزمة رد


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

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

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

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

  1. <Provider store> - يسمح لك بإنشاء غلاف لتطبيق React وجعل حالة Redux متاحة لجميع مكونات الحاوية في التدرج الهرمي الخاص بها.
  2. connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options]) - يسمح لك بإنشاء مكونات عالية الترتيب. يعد ذلك ضروريًا لإنشاء مكونات الحاوية بناءً على مكونات React الأساسية.

قم بتثبيت رد الفعل من أجل استخدام هذه الحزمة في المشروع على النحو التالي:

 npm install react-redux --save 

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

 import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import createStore from './createReduxStore'; const store = createStore(); const rootElement = document.getElementById('root'); ReactDOM.render(( <Provider store={store}>   <AppRootComponent /> </Provider> ), rootElement); 

الآن يمكنك إنشاء مكونات الحاوية المتصلة بمستودع Redux. يتم ذلك ضمن التسلسل الهرمي لـ AppRootComponent باستخدام واجهة برمجة التطبيقات connect() .

متى تستخدم ربط ()؟


componentsإنشاء مكونات الحاوية


كما ذكرنا من قبل ، يتم استخدام واجهة برمجة التطبيقات connect() API connect() بتفاعل red-redux لإنشاء مكونات الحاوية المتصلة بمستودع Redux. يتم الحصول على التخزين الذي تتصل به من أعلى سلف للمكون باستخدام آلية سياق التفاعل. ليست هناك حاجة إلى وظيفة connect() إذا قمت بإنشاء مكونات العرض التقديمي فقط.

إذا كنت في مكون React ، تحتاج إلى تلقي البيانات من المستودع ، أو كنت بحاجة إلى إرسال الإجراءات ، أو كنت بحاجة إلى تنفيذ كليهما ، يمكنك تحويل مكوِّن عادي إلى مكوّن حاوية بلفه في مكوّن عالي الترتيب يتم إرجاعه بواسطة connect() من رد فعل رد فعل. إليك ما يبدو عليه:

 import React from 'react'; import { connect } from 'react-redux'; import Profile from './components/Profile'; function ProfileContainer(props) { return (   props.loggedIn     ? <Profile profile={props.profile} />     : <div>Please login to view profile.</div> ) } const mapStateToProps = function(state) { return {   profile: state.user.profile,   loggedIn: state.auth.loggedIn } } export default connect(mapStateToProps)(ProfileContainer); 

▍ القضاء على الحاجة إلى الاشتراك يدويًا في Redux storage


يمكنك إنشاء مكون الحاوية بنفسك وتوقيع المكون يدويًا على مستودع Redux باستخدام الأمر store.subscribe() . ومع ذلك ، يعني استخدام وظيفة connect() تطبيق بعض التحسينات والتحسينات في الأداء التي قد لا تتمكن من استخدامها عند استخدام آليات أخرى.

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

 import React, { Component } from 'react'; import store from './reduxStore'; import Profile from './components/Profile'; class ProfileContainer extends Component { state = this.getCurrentStateFromStore() getCurrentStateFromStore() {   return {     profile: store.getState().user.profile,     loggedIn: store.getState().auth.loggedIn   } } updateStateFromStore = () => {   const currentState = this.getCurrentStateFromStore();     if (this.state !== currentState) {     this.setState(currentState);   } } componentDidMount() {   this.unsubscribeStore = store.subscribe(this.updateStateFromStore); } componentWillUnmount() {   this.unsubscribeStore(); } render() {   const { loggedIn, profile } = this.state;     return (     loggedIn       ? <Profile profile={profile} />       : <div>Please login to view profile.</div>   ) } } export default ProfileContainer; 

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

إذا كان تطبيق React الخاص بك يستخدم مستودعات Redux متعددة ، فإن connect() تجعل من السهل تحديد المستودع المحدد الذي يجب توصيل مكون الحاوية به.

توصيل التشريح ()


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

نظرًا لأن الدالة تُرجع مكوِّنًا عالي الترتيب ، يجب استدعاؤها مرة أخرى ، لتمرير مكوّن التفاعل الأساسي من أجل تحويله إلى مكوّن حاوية:

 const ContainerComponent = connect()(BaseComponent); 

هنا هو توقيع وظيفة connect() :

 connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options]) 

▍ حجة mapStateToProps


الوسيطة mapStateToProps هي دالة تقوم بإرجاع إما كائن عادي أو دالة أخرى. يؤدي تمرير هذه الوسيطة connect() اشتراك مكون الحاوية في تحديثات مستودع Redux. هذا يعني أنه سيتم استدعاء وظيفة mapStateToProps كل مرة تتغير فيها حالة المستودع. إذا لم تكن مهتمًا بمراقبة تحديثات الحالة ، فمرر connect() كقيمة هذه الوسيطة إلى undefined أو null .

يتم mapStateToProps وظيفة mapStateToProps ، والثانية اختيارية. المعلمة الأولى هي الحالة الحالية لمستودع Redux. المعلمة الثانية ، إذا تم تمريرها ، هي كائن الخصائص التي تم تمريرها إلى المكون:

 const mapStateToProps = function(state) { return {   profile: state.user.profile,   loggedIn: state.auth.loggedIn } } export default connect(mapStateToProps)(ProfileComponent); 

إذا تم إرجاع كائن عادي من mapStateToProps ، فسيتم stateProps كائن stateProps إرجاعه مع خصائص المكون. يمكنك الوصول إلى هذه الخصائص في المكون على النحو التالي:

 function ProfileComponent(props) { return (   props.loggedIn     ? <Profile profile={props.profile} />     : <div>Please login to view profile.</div> ) } 

إذا mapStateToProps دالة ، فسيتم استخدام هذه الوظيفة ك mapStateToProps لكل مثيل للمكون. يمكن أن يكون هذا مفيدًا لتحسين أداء العرض والتدوين.

▍ الوسيطة mapDispatchToProps


يمكن أن تكون الوسيطة mapDispatchToProps إما كائنًا أو دالة تقوم بإرجاع إما كائن عادي أو دالة أخرى. من أجل توضيح mapDispatchToProps بشكل أفضل ، نحتاج إلى مولدات العمل. لنفترض أن لدينا المولدات التالية:

 export const writeComment = (comment) => ({ comment, type: 'WRITE_COMMENT' }); export const updateComment = (id, comment) => ({ id, comment, type: 'UPDATE_COMMENT' }); export const deleteComment = (id) => ({ id, type: 'DELETE_COMMENT' }); 

الآن فكر في الاستخدامات المختلفة لـ mapDispatchToProps .

التنفيذ الافتراضي الافتراضي


إذا لم تستخدم تطبيق mapDispatchToProps الخاص بك ، الذي يمثله كائن أو دالة ، فسيتم استخدام تطبيق قياسي ، والذي سينفذ طريقة مستودع dispatch() كخاصية للمكون. يمكنك استخدام هذه الخاصية في مكون مثل هذا:

 import React from 'react'; import { connect } from 'react-redux'; import { updateComment, deleteComment } from './actions'; function Comment(props) { const { id, content } = props.comment; //    props.dispatch() const editComment = () => props.dispatch(updateComment(id, content)); const removeComment = () => props.dispatch(deleteComment(id)); return (   <div>     <p>{ content }</p>     <button type="button" onClick={editComment}>Edit Comment</button>     <button type="button" onClick={removeComment}>Remove Comment</button>   </div> ) } export default connect()(Comment); 

نقل الكائن


إذا تم استخدام كائن كوسيطة إلى mapDispatchToProps ، mapDispatchToProps كل وظيفة في الكائن mapDispatchToProps إجراء mapDispatchToProps في استدعاء لطريقة مستودع dispatch() ، والتي ستسمح mapDispatchToProps مباشرة. سيتم دمج الكائن الناتج مع مولدات الإجراءات ، dispatchProps ، مع خصائص المكون.

يوضح المثال التالي مثالًا على إنشاء وسيطة mapDispatchToProps ، وهو كائن يحتوي على مولدات الإجراءات ، بالإضافة إلى كيفية استخدام المولدات كخصائص لمكون React:

 import React from 'react'; import { connect } from 'react-redux'; import { updateComment, deleteComment } from './actions'; function Comment(props) { const { id, content } = props.comment; // ,   ,   const editComment = () => props.updatePostComment(id, content); const removeComment = () => props.deletePostComment(id); return (   <div>     <p>{ content }</p>     <button type="button" onClick={editComment}>Edit Comment</button>     <button type="button" onClick={removeComment}>Remove Comment</button>   </div> ) } //     const mapDispatchToProps = { updatePostComment: updateComment, deletePostComment: deleteComment } export default connect(null, mapDispatchToProps)(Comment); 

نقل الوظيفة


عند استخدام الدالة mapDispatchToProps كوسيطة mapDispatchToProps يجب أن يهتم المبرمج بإعادة كائن dispatchProps ، الذي ينفذ ربط مولدات الإجراءات باستخدام طريقة التخزين dispatch() . تقبل هذه الوظيفة ، كمعلمة أولى ، طريقة مستودع dispatch() . كما هو الحال مع mapStateToProps ، يمكن أن تقبل الوظيفة أيضًا المعلمة الاختيارية الخاصة ownProps ، والتي تصف التعيين بالخصائص الأصلية التي تم تمريرها إلى المكون.

إذا أعادت هذه الوظيفة وظيفة أخرى ، فسيتم استخدام الدالة التي تم إرجاعها على أنها mapDispatchToProps ، والتي يمكن أن تكون مفيدة لتحسين أداء العرض والتذكر.

يمكن استخدام وظيفة المساعد bindActionCreators() من Redux داخل هذه الوظيفة لربط مولدات العمل مع طريقة dispatch() .

يوضح المثال التالي استخدام وظيفة في وظيفة mapDispatchToProps . كما يوضح العمل مع الوظيفة المساعدة bindActionCreators() ، والتي تستخدم لربط مولدات العمل للعمل مع التعليقات على props.actions

 import React from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import * as commentActions from './actions'; function Comment(props) { const { id, content } = props.comment; const { updateComment, deleteComment } = props.actions; //    props.actions const editComment = () => updateComment(id, content); const removeComment = () => deleteComment(id); return (   <div>     <p>{ content }</p>     <button type="button" onClick={editComment}>Edit Comment</button>     <button type="button" onClick={removeComment}>Remove Comment</button>   </div> ) } const mapDispatchToProps = (dispatch) => { return {   actions: bindActionCreators(commentActions, dispatch) } } export default connect(null, mapDispatchToProps)(Comment); 

▍Argument mergeProps


إذا تم تمرير الوسيطة mergeProps إلى connect() ، فهي دالة تأخذ المعلمات الثلاث التالية:

  • stateProps هو عنصر الخاصية الذي تم ارجاعه من استدعاء mapStateToProps() .
  • dispatchProps - كائن خاصية مع مولدات الإجراءات من mapDispatchToProps() .
  • ownProps - الخصائص الأصلية التي حصل عليها المكون.

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

إذا لم ينجح connect() تمرير هذه الوظيفة ، فسيتم استخدام تنفيذها القياسي:

 const mergeProps = (stateProps, dispatchProps, ownProps) => { return Object.assign({}, ownProps, stateProps, dispatchProps) } 

gحجة تمثل كائنًا مع معلمات


يحتوي كائن اختياري ، تم تمريره إلى الدالة connect() كوسيطة رابعة ، على معلمات مصممة لتغيير سلوك هذه الوظيفة. لذا ، connect() هو تطبيق خاص connectAdvanced() ، فهو يقبل معظم المعلمات المتاحة ل connectAdvanced() ، بالإضافة إلى بعض المعلمات الإضافية.

فيما يلي صفحة التوثيق ، بعد القراءة ، يمكنك معرفة المعلمات التي يمكن استخدامها مع connect() ، وكيفية تعديل سلوك هذه الوظيفة.

باستخدام وظيفة connect ()


reat إنشاء التخزين


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

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

 import React from 'react'; import { connect } from 'react-redux'; class NewComment extends React.Component { input = null writeComment = evt => {   evt.preventDefault();   const comment = this.input.value;     comment && this.props.dispatch({ type: 'WRITE_COMMENT', comment }); } render() {   const { id, content } = this.props.comment;     return (     <div>       <input type="text" ref={e => this.input = e} placeholder="Write a comment" />       <button type="button" onClick={this.writeComment}>Submit Comment</button>     </div>   ) } } export default connect()(NewComment); 

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

تحديد خاصية المخزن في مكون الحاوية


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

 import React from 'react'; import store from './reduxStore'; import NewComment from './components/NewComment'; function CommentsApp(props) { return <NewComment store={store} /> } 

تعيين خاصية المخزن في المكون <Provider>


إذا كنت تريد تعيين مستودع Redux للتطبيق مرة واحدة فقط ، فستكون مهتمًا بالطريقة التي سنأخذها في الاعتبار الآن. وعادة ما تكون مناسبة للتطبيقات التي تستخدم مستودع Redux واحد فقط.

توفر حزمة رد الفعل للمطور المطور <Provider> ، والذي يمكن استخدامه لتغليف المكون الجذر للتطبيق. يقبل عقار store . من المفترض أن يكون ارتباطًا إلى مستودع Redux ، الذي من المقرر استخدامه في التطبيق. يتم تمرير خاصية store ، وفقًا للتسلسل الهرمي للتطبيق ، إلى مكونات الحاوية ، باستخدام آلية سياق التفاعل:

 import React from 'react'; import ReactDOM from 'react-dom'; import store from './reduxStore'; import { Provider } from 'react-redux'; import NewComment from './components/NewComment'; function CommentsApp(props) { return <NewComment /> } ReactDOM.render(( <Provider store={store}>   <CommentsApp /> </Provider> ), document.getElementById('root')) 

AccessOpenProps منظمة الوصول


كما سبق ذكره ، يمكن الإعلان عن mapStateToProps و mapDispatchToProps mapStateToProps connect() باستخدام المعلمة الثانية ownProps ، وهي خصائص المكون.
ومع ذلك ، هناك مشكلة واحدة. إذا كان عدد المعلمات المطلوبة للوظيفة المعلنة أقل من 2 ، فلن يتم إرسال ownProps . ولكن إذا تم الإعلان عن وظيفة بدون معلمات مطلوبة أو مع معلمتين على الأقل ، فسيتم تمرير ownProps .

فكر في عدة خيارات للعمل مع ownProps .

إعلان وظيفة بدون معلمات


 const mapStateToProps = function() { console.log(arguments[0]); // state console.log(arguments[1]); // ownProps }; 

في هذه الحالة ، ownProps تمرير ownProps ، حيث يتم الإعلان عن الوظيفة بدون المعلمات المطلوبة. ونتيجة لذلك ، ستعمل التعليمات البرمجية التالية المكتوبة باستخدام بناء الجملة الجديدة لمعلمات ES6 المتبقية:

 const mapStateToProps = function(...args) { console.log(args[0]); // state console.log(args[1]); // ownProps }; 

إعلان دالة بمعلمة واحدة


خذ بعين الاعتبار المثال التالي:

 const mapStateToProps = function(state) { console.log(state); // state console.log(arguments[1]); // undefined }; 

هناك معلمة واحدة فقط ، state . نتيجة لذلك ، تأخذ arguments[1] القيمة undefined نظرًا لعدم إرسال ownProps .

إعلان الوظيفة مع المعلمة الافتراضية


 const mapStateToProps = function(state, ownProps = {}) { console.log(state); // state console.log(ownProps); // {} }; 

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

إعلان وظيفة بمعلمتين


 const mapStateToProps = function(state, ownProps) { console.log(state); // state console.log(ownProps); // ownProps }; 

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

الملخص


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

أعزائي القراء! هل تستخدم رد الفعل في مشاريعك؟

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


All Articles