Redux: كيف تستدعي الإجراءات بدون استخدامconnect؟

تم إنشاؤها على ٣٠ يوليو ٢٠١٥  ·  32تعليقات  ·  مصدر: reduxjs/redux

لدي حاوية رأس تمرر بيانات الصورة (عنوان url ، الحجم) إلى مكون رأس باستخدام

@connect(state => ({
  header: state.header
}))
export default class HeaderContainer extends Component {
 /// pass props.header data to child Header which renders image.
}

ثم لدي مكون آخر يحتاج إلى استدعاء إجراءات الرأس لتحديث حالة الرأس. إنها لا تستخدم الدولة ، إنها فقط تطلق الأعمال. أحتاج إلى Afaik أن أفعل شيئًا كهذا:

const { dispatch } = this.props
const actions = bindActionCreators(headerActions, dispatch)

المشكلة هي أن this.props.dispatch تبدو متاحة فقط عند استخدام connect decorator. المكون الثاني غير مهتم بحالة الرأس على الإطلاق. هل أحتاج حقًا إلى استخدام الاتصال هنا أم أنه يمكنه بطريقة ما ربط الإجراءات بطريقة مختلفة؟ من الخطأ استخدام connect إذا لم أستخدم البيانات.

question

التعليق الأكثر فائدة

يمكنك تمرير dispatch إلى هذا المكون يدويًا كخاصية.

ال 32 كومينتر

لست متأكدًا من أنها طريقة "صحيحة" أم لا ، ولكن يمكنك الوصول إلى المتجر من خلال السياق. راجع المكون Connector على سبيل المثال:
https://github.com/gaearon/react-redux/blob/master/src/components/createConnector.js

أنا لا أتبعك. أنا بخير تمامًا للوصول إلى المتجر باستخدامconnect. أنا أبحث عن طريقة لربط / استدعاء الإجراءات في أحد المكونات دون استخدامconnect.

الوظيفة dispatch هي إحدى طرق المتجر. إذا كنت بحاجة إليه في المكون الخاص بك ولكنك لا تريد استخدام @connect ، فيمكنك الوصول إلى المتجر من خلال السياق واستخدام طريقة الإرسال الخاصة به:

class MyComponent extends Compoenent {
    static contextTypes = {
        store: React.PropTypes.object.isRequired,
    }

    render() {
         const { dispatch } = this.context.store
         const actions = bindActionCreators(headerActions, dispatch)
    }
}

يجب أن تمرر الإرسال من المكون الرئيسي ، أو الإجراء المرتبط بالفعل بالإرسال. هذه هي الطريقة التي أؤمن بها ، يعمل السياق أيضًا ، وإن كان حلاً

شكرا لشرح هذا! استلمتها الان.

يمكنك تمرير dispatch إلى هذا المكون يدويًا كخاصية.

أنا أيضا في حيرة من هذا الموضوع.

إذا فهمت بشكل صحيح ، فإننا نحتاج إما أن يكون لدينا dispatch متاحًا من خلال خاصيات أحد المكونات (لتتمكن من إرسال الإجراءات من هذا المكون) أو لمنح منشئي الإجراءات المرتبطين بالفعل بـ dispatch ، من المكون الرئيسي. لكن كلا الحلين يتطلبان وجود مكون أصلي connect ed بحيث يتم توفير الإرسال له عبر الدعائم الخاصة به.

لذلك في النهاية ، نقوم فقط بنقل اعتمادنا على dispatch إلى مكون رئيسي. وكيف ستفعل ذلك إذا لم يكن هناك أحد الوالدين connect ed؟

على سبيل المثال ، ماذا لو كنا في تسلسل هرمي عميق للمكونات:

Provider
  Router
    AppContainer
     ...
       ...
         ...
           TheComponentThatNeedDispatch

وإذا لم يحتاج أي من الوالدين إلى الاتصال بحالة الإعادة؟

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

أعلم أنه لا يزال بإمكاننا الوصول إلى dispatch من سياق مكون (عبر store.dispatch ) ولكن نظرًا لأنها ليست الطريقة الموصى بها ...

ما رأيك في ذلك؟

شكر!

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

لماذا هذا غريب؟ فكر في connect كـ "connect to Redux" وليس فقط "الاتصال بجزء من حالة Redux". ثم يكون من المنطقي: لتكون قادرًا على dispatch إما المكون نفسه ، أو بعض العنصر الأصل ، يجب أن يكون connect() ed لإعادة.

مع واجهة برمجة تطبيقات React Redux الحالية ، ليس من الملائم الاتصال بـ Redux بدون تحديد الحالة أيضًا. يجب عليك كتابة شيء مثل connect(state => ({}))(MyComponent) (إرجاع الكائن الفارغ). هذا هو السبب في أننا كنا نستكشف واجهات برمجة تطبيقات بديلة لها تجعلها مواطنًا من الدرجة الأولى dispatch وتخطط لإضافة واجهة برمجة تطبيقات للاستيلاء على " dispatch ".

هل لهذا معنى؟

فكر في الاتصال على أنه "اتصال بـ Redux" وليس فقط "الاتصال بجزء من حالة Redux".

تماما من المنطقي الآن :).

لا استطيع الانتظار لاستخدام API الجديد .

شكرًا جزيلاً ، استخدام Redux هو نعمة!

هذا يبدو رائعا!

gaearon Hey Dan ، هل يمكن أن تعطيني نصيحة حول كيفية استخدام bindActionCreators مع المكونات المتداخلة:

"AddProduct" - متصل بـ redux (انظر أدناه)
__ "قائمة المنتجات"
____ "ProductView".

أريد أن يكون ProductView قادرًا على الإرسال ، ولكن فقط "إضافة منتج" الرئيسي لديه:

function appState(state) {
    return {...};
}

export default connect(appState)(AddProduct)

يمكنك إما connect() المكون المتداخل أيضًا ، أو يمكنك تمرير dispatch إليه كدعم.

شكرًا دان ، حقًا أقدر مساعدتك. حقا أحب إعادة أيضا!

سؤال آخر إذا جاز لي:
هل يمكنني وضع طلبات نشر API للخادم من داخل المخفض نفسه؟
عندما أقوم بالنشر في قاعدة البيانات (mongodb) ، يحصل العنصر على "_id" الذي أود الحصول عليه في حالة إعادة الإرسال الخاصة بي. هل يجب وضع الإرسال باعتباره رد اتصال لطلب POST؟

شكرا لك

هل يمكنني وضع طلبات نشر API للخادم من داخل المخفض نفسه؟

بالتأكيد لا ، يجب أن تكون المخفضات وظائف خالصة خالية من أي آثار جانبية.

عندما أقوم بالنشر في قاعدة البيانات (mongodb) ، يحصل العنصر على "_id" الذي أود الحصول عليه في حالة إعادة الإرسال الخاصة بي. هل يجب وضع الإرسال باعتباره رد اتصال لطلب POST؟

نعم.

يرجى الاطلاع على هذا الدليل: http://rackt.github.io/redux/docs/advanced/AsyncActions.html

شكرا دان ، يعمل بشكل رائع (ذ)

إذا كنت تستخدم عرض الخادم ، لنفترض أن تسجيل دخول المستخدم الحالي ،
هل يمكنني تخطي الجلب غير المتزامن من المتجر ، والقيام بذلك على الخادم؟

إذا كنت تستخدم عرض الخادم ، فلنقل السماح للمستخدم الحالي بتسجيل الدخول ، فهل يمكنني تخطي الجلب غير المتزامن من المتجر ، والقيام بذلك على الخادم؟

يمكنك إنشاء مخزن على الخادم ، والانتظار حتى انتهاء الإجراءات غير المتزامنة ، ثم التقديم.
راجع أيضًا http://rackt.github.io/redux/docs/recipes/ServerRendering.html

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

mpoisot : لأنه

markerikson ، يجب أن أعرف بالفعل جميع createStore . أتخيل الاتصال بـ bindAllActionCreators(store.dispatch) في السطر التالي.

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

هل هناك عقوبة أداء رهيبة لفعل هذا؟ أم أنه يقود بطريقة ما إلى طريق رهيب إلى جحيم الترميز؟

mpoisot : ليس في الحقيقة أي مشاكل في الأداء يمكنني التفكير فيها. ومع ذلك ، فإنه يحد من قابلية الاختبار وإعادة الاستخدام.

يؤدي الاستخدام السليم لـ connect إلى اتباع نهج خفيف لحقن التبعية. المكوّن "العادي" يعرف فقط أنه يتم إعطاؤه بعض الوظائف كخاصية ، ويجب أن يستدعي هذه الوظيفة حسب الحاجة. لا يهم في الواقع ما إذا كانت عبارة عن رد اتصال تم تمريره مباشرة من قبل بعض المكونات الرئيسية ، أو منشئ إجراء ملزم مسبقًا. هذا يعني أنه يمكن إعادة استخدام المكون بطريقة مباشرة ، كما أنه يجعل اختباره أسهل كثيرًا. من ناحية أخرى ، يؤدي القيام بشيء مثل الاستيراد المباشر للمتجر إلى ربط المكون بمثيل المتجر المحدد والتنفيذ ، وهذا هو سبب عدم تشجيعه (وفقًا للأسئلة الشائعة حول Redux: http://redux.js.org/docs/faq/ StoreSetup.html # store-setup-multiple-Stores). إذا فهمت ما تسأل عنه بشكل صحيح ، فهو في الأساس نفس الموقف مثل الاستيراد المباشر إلى المتجر والإشارة إليه.

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

مما يجعلني أفكر ، بالتأكيد يمكنك إنشاء كائن تخزين فردي يمكن تحديث متجره بمخازن مختلفة للاختبار؟ بدلاً من تصدير المتجر نفسه مباشرةً ، قم بإعادته عبر StoreSingleton.getStore() ، وقم بتغيير المتجر الحالي عبر StoreSingleton.setStore() . لذلك فيما يتعلق بالاختبار ، لن تكون مرتبطًا بمثيل واحد من المتجر. ومع ذلك ، يمكنني معرفة سبب عدم نجاح ذلك في بيئة خادم مترابطة.

mpoisot لقد وصفت للتو ما يفعله المزود / الاتصال. ؛)

غالبًا ما يكون لدي عنصر "غبي" يحتاج يومًا ما إلى إرسال (أو إجراء محدد مسبقًا). لذلك أقوم بلفه بالاتصال ، أو ربما أنقل أشياء من مكون محتوي متصل. غالبًا ما يبدو الأمر وكأنه الكثير من دعائم الأسلاك والتمرير فقط لتجنب الإرسال الذي يمكن الوصول إليه عالميًا. بالنسبة لـ mapStateToProps () ، هناك مكاسب رائعة في الأداء مع Provider / connect (). ولإعادة استخدام المكونات الغبية ، فمن المنطقي بالتأكيد استخراج منطق الإرسال إلى مكون الترتيب الأعلى.

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

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

نعم ، بعض تجارب "المكون / الحالة المغلفة" التي رأيتها تعمل مع هذا النهج بالضبط. الشيء الرائع في هذه الفكرة هو أن المكونات الأخرى لا تحتاج إلى معرفة أي شيء تغير ، لأن مكونات الغلاف لا تزال تستحوذ على this.context.store وتستخدم dispatch حسب الحاجة.

لقد كنت على كلا الجانبين من هذا -

في تطبيقي الأساسي ، نتعامل مع المتجر باعتباره منفردًا ونستخدم وظيفة getStore() المتاحة عالميًا. نحن لا نستخدم العرض من جانب الخادم. ما زلنا نستخدم Provider و connect مقابل mapStateToProps .

من ناحية أخرى ، لقد أنشأت تطبيقًا تجريبيًا حيث أقوم بلف المتجر (مثل jimbolla و markerikson المذكورة) في أماكن مختلفة داخل التسلسل الهرمي للمكونات ، وكلاهما dispatch و getState can التغيير في جميع أنحاء التطبيق ، مما يعني أنه يجب أن يتم توصيلهم سلكيًا في جميع أنحاء التطبيق (إما عبر context أو props ) ولا يمكن أن يكونوا منفردون.

اعتمادًا على ما تريد تحقيقه ، أعتقد أن أشياء المتجر الفردي قابلة للتطبيق ، لكنني شخصيًا أتحرك ببطء بعيدًا عنها.

بلى. أنت بالتأكيد _يمكنك_ التعامل مع المتجر باعتباره منفردًا يمكن الوصول إليه ، لكنه يحدك ، ولا يعتبر اصطلاحيًا ، ولا أرى أي ميزة حقيقية للقيام بذلك.

شكرًا ، تعليقات رائعة. هل يمكن لأي شخص نشر رابط يعرض بعض تغليف المتجر؟

تضمين التغريدة

إليك أحد تعليقات دان التي توضح كيف يمكن أن يكون التفاف dispatch مفيدًا:

https://github.com/reactjs/redux/issues/822#issuecomment -145271384

قد تضطر إلى قراءة الموضوع بأكمله لفهم الدافع بشكل أفضل.

على وجه الخصوص ، لاحظ كيف يتم تغليف dispatch (لقد أبرزته):

wrappeddispatch

آسف لاختطاف هذه المشاركة القديمة لأنني أواجه ارتباكًا مشابهًا ، وأرغب في إرسال إجراء بدون اتصال.

export default class App extends Component {
...
  componentDidMount() {
    //registering event listener
    BackgroundGeolocation.on('location', this.onLocation, this.onError);
  }

  onLocation(location) {
   //wishing to dispatch an action to update variable in store
  }

  render() {
    return (
      <Provider store={store}>
        <AlertProvider>
          <MainNavigator screenProps={{ isConnected: this.state.isConnected }} />
        </AlertProvider>
      </Provider>
    );
  }
}

بناءً على ما أفهمه ، لا يمكنني الاتصال بالمخزن في هذا المكون لأننا نقوم فقط بتكوين وتمرير المتجر إلى Provider . كيف يمكنني إرسال إجراء في حدث onLocation ؟

isaaclem : حسنًا ، في هذه الحالة المحددة ، لديك _do_ إشارة إلى المتجر ، لذا يمكنك الاتصال مباشرة بـ store.dispatch(someAction) .

قد يكون الخيار الآخر هو إعادة هيكلة هيكل المكون الخاص بك بحيث يقوم بعض المكونات _ داخل_ <Provider> بسلوك تحديد الموقع الجغرافي في الخلفية ، ويمكن أيضًا توصيله.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات