لقد قرأت الكثير من الوثائق - في جميع المواقع الشهيرة - ولكن لم أجد إجابة في أي مكان. أسأل هنا لمعرفة ما إذا كنت قد فاتني بعض الوثائق ، أو جزء حيوي من الفهم.
المشكلة التي أراها هي أن وظيفة mapStateToProps () للمكوِّن الخاص بي تُستدعى مرة واحدة فقط (عند التهيئة). لا يتم استدعاؤه مرة أخرى ، حتى عندما يتم استدعاء المخفض. بدأت أعتقد أن السبب في ذلك هو أنني لا أفهم كيف ترتبط الإجراءات / المخفضات / الدعائم معًا.
اسمحوا لي أن أقول أولاً ما _فعل _:
لكن ... لم أجد وصفًا لكيفية ارتباط الإجراءات والمخفضات و mapStateToProps ببعضها البعض. أسئلتي:
هل مررت بـ http://redux.js.org/docs/Troubleshooting.html وتحققت من أن حالتك ليست واحدة من المشكلات التي تصفها؟
أعتقد أن المتجر كائن ، له خصائص تحتوي على بيانات حول حالة التطبيق. يمكن أن تكون خصائص المستوى الأعلى كائنات توفر شجرة فرعية للاحتفاظ بمعلومات حول جزء من التطبيق. هل هذا صحيح؟
نعم. المتجر يحمل كائن حالة المستوى الأعلى داخليًا. يوفر الوصول إلى هذا الكائن من store.getState()
. يتوافق هذا الكائن مع كل ما ترجع إليه من مخفض الجذر ، وغالبًا ما يشبه الشجرة.
عندما يتم إرسال إجراء إلى المتجر ، ما الخاصية (أو الشجرة الفرعية للمتجر) التي يتم تحديثها؟ يبدو أن هناك إنشاءًا تلقائيًا / ارتباطًا بخاصية داخل المتجر ، ولكن كيف يتم تحديد ذلك؟
لا ، لا يوجد إنشاء تلقائي لأي شيء. يبدأ المتجر للتو في الإشارة إلى نتيجة استدعاء مخفض الجذر.
إذا كان مخفض الجذر الخاص بك هو وظيفة كتبتها بنفسك ، فإن نتيجتها هي ما ستحصل عليه بعد إرسال إجراء:
function counter(state = 0, action) {
if (action.type === 'INCREMENT') {
return state + 1; // will become the next value of store.getState() after store.dispatch()
}
return state;
}
إذا قمت بإنشاء مخفض الجذر بشيء مثل combineReducers({ foo, bar })
، فسيكون كما لو كنت قد كتبت مخفض الجذر يدويًا يشبه هذا:
function root(state = {}, action) {
return {
foo: foo(state.foo, action),
bar: bar(state.bar, action)
}
}
هذا هو المكان الذي تأتي منه غالبًا ممتلكات الدولة. يتم تحديد قيمها من خلال ما أعادته مخفضات foo
و bar
أثناء التعامل مع الإجراء ، على التوالي ، لذا فأنت تتحكم فيها بالكامل مرة أخرى.
كيف "تعرف" mapStateToProps للاستماع إلى التحديثات على الممتلكات / الجزء المناسب من المتجر؟ ما الذي يربط بينهما؟
يمكنك تمرير mapStateToProps
إلى الوظيفة connect()
. يقوم بإنشاء مكون يستخدم store.subscribe()
للاستماع إلى كل تغيير في المتجر. عندما يتغير المتجر ، يقرأ المكون الذي تم إنشاؤه store.getState()
ويمرره إلى mapStateToProps()
لتحديد العناصر التالية المراد تمريرها. إذا تغيروا ، فسيتم إعادة تقديم المكون الخاص بك معهم.
كيف يمكنني تصحيح هذا؟ ما الذي يجب أن أفعله لمعرفة لماذا لا يبدو أن إرسال الإجراء يؤدي إلى إطلاق خريطةStateToProps؟
أضف برمجية وسيطة مثل https://github.com/theaqua/redux-logger. تحقق من أن الحالة يتم تحديثها بعد الإجراء بالطريقة التي تتوقعها. إذا لم يتم استدعاء mapStateToProps
، فهذا يعني ذلك
dispatch()
واتصلت للتو بمنشئ إجراء ،connect()
عناء استدعاء mapStateToProps()
.تم وصف كلتا الحالتين في http://redux.js.org/docs/Troubleshooting.html.
في المستقبل ، نطلب منك محاولة طرح الأسئلة على StackOverflow أولاً ، واستخدام أداة تعقب المشكلات عندما تكون واثقًا من وجود خطأ في المكتبة يمكنك إعادة إنتاجه باستمرار باستخدام مثال يمكنك مشاركته.
شكر!
الرد بالترتيب:
{ users : {}, posts : {}, comments : {}, ui : {} }
. راجع http://redux.js.org/docs/FAQ.html#reducers -share-state و http://redux.js.org/docs/FAQ.html#organizing -state-nested-data.combineReducers
التي تأتي مع Redux من السهل الحصول على وظيفة مخفض محددة تكون مسؤولة عن إدارة التحديثات لشريحة معينة من البيانات ، مثل: const combinedReducer = combineReducers({users : userReducer, posts : postReducer, comments : commentsReducer, ui : uiReducer});
connect()
، ثم تستدعي المكون mapStateToProps
لمعرفة ما إذا كان أي من البيانات المستخرجة قد تغير منذ آخر مرة. لا يوجد اشتراك محدد للولاية المتداخلة. راجع http://redux.js.org/docs/FAQ.html#store -setup-subscriptions.نأمل أن يساعد ذلك في توضيح الأمور.
أبعد من ذلك ، كما قال دان: تعتبر أسئلة الاستخدام أكثر ملاءمة بشكل عام لـ Stack Overflow. أيضًا ، لدى مجتمع Reactiflux على Discord مجموعة من قنوات الدردشة المخصصة للتقنيات المتعلقة بـ React ، بما في ذلك Redux ، وهناك دائمًا عدد من الأشخاص يتجولون على استعداد للإجابة على الأسئلة. يوجد رابط دعوة على https://www.reactiflux.com .
@ richb-hanover ربما تكون قد شاهدت المقارنة السطحية التي يتم إجراؤها بواسطة وصلة رد الفعل والإعادة. هذا يعني أن الكائنات المتداخلة ضمن كائنات أخرى لن تؤدي إلى إعادة عرضها حتى إذا تم تعديلها لأنه يتم فحص مفتاح الجذر فقط من أجل التعديلات.
http://redux.js.org/docs/faq/ReactRedux.html#why -isnt-my-component-re-rendering-or-my-mapstatetoprops-running
@ richb-hanover في حالتي ، اكتشف gaearon المشكلة:
أو أعاد المخفض قيمة مماثلة مرجعية ، لذا لم يكلف connect () عناء استدعاء mapStateToProps ().
كنت أستخدم هذا الإصلاح وكان هذا هو الرمز الناتج
const mapStateToProps = (state, props) => {
return { id: props.id, currentState: state[props.id] };
}
const mapDispatchToProps = (dispatch) => {
return {
increment: (id) => {
dispatch({ type: 'INCREMENT', id: id })
}
}
}
const DumbListItem = ({
increment,
id,
currentState
}) => (
<div>
<li onClick={() => increment()}>{id}</li>
<span>{currentState}</span>
</div>
);
export const ConnectedListItem = connect(
mapStateToProps,
mapDispatchToProps
)(DumbListItem);
نظرًا لأنني لم أمرر المعلمة id
لاستدعاء الزيادة (إما increment(id)
في القالب ، أو عبر المعلمة الثانية في mapDispatchToProps
) ، فإن المتجر لم يفعل التحديث بشكل صحيح ، لذا تحقق مما إذا كانت هذه هي مشكلتك.
التعليق الأكثر فائدة
هل مررت بـ http://redux.js.org/docs/Troubleshooting.html وتحققت من أن حالتك ليست واحدة من المشكلات التي تصفها؟
نعم. المتجر يحمل كائن حالة المستوى الأعلى داخليًا. يوفر الوصول إلى هذا الكائن من
store.getState()
. يتوافق هذا الكائن مع كل ما ترجع إليه من مخفض الجذر ، وغالبًا ما يشبه الشجرة.لا ، لا يوجد إنشاء تلقائي لأي شيء. يبدأ المتجر للتو في الإشارة إلى نتيجة استدعاء مخفض الجذر.
إذا كان مخفض الجذر الخاص بك هو وظيفة كتبتها بنفسك ، فإن نتيجتها هي ما ستحصل عليه بعد إرسال إجراء:
إذا قمت بإنشاء مخفض الجذر بشيء مثل
combineReducers({ foo, bar })
، فسيكون كما لو كنت قد كتبت مخفض الجذر يدويًا يشبه هذا:هذا هو المكان الذي تأتي منه غالبًا ممتلكات الدولة. يتم تحديد قيمها من خلال ما أعادته مخفضات
foo
وbar
أثناء التعامل مع الإجراء ، على التوالي ، لذا فأنت تتحكم فيها بالكامل مرة أخرى.يمكنك تمرير
mapStateToProps
إلى الوظيفةconnect()
. يقوم بإنشاء مكون يستخدمstore.subscribe()
للاستماع إلى كل تغيير في المتجر. عندما يتغير المتجر ، يقرأ المكون الذي تم إنشاؤهstore.getState()
ويمرره إلىmapStateToProps()
لتحديد العناصر التالية المراد تمريرها. إذا تغيروا ، فسيتم إعادة تقديم المكون الخاص بك معهم.أضف برمجية وسيطة مثل https://github.com/theaqua/redux-logger. تحقق من أن الحالة يتم تحديثها بعد الإجراء بالطريقة التي تتوقعها. إذا لم يتم استدعاء
mapStateToProps
، فهذا يعني ذلكdispatch()
واتصلت للتو بمنشئ إجراء ،connect()
عناء استدعاءmapStateToProps()
.تم وصف كلتا الحالتين في http://redux.js.org/docs/Troubleshooting.html.
في المستقبل ، نطلب منك محاولة طرح الأسئلة على StackOverflow أولاً ، واستخدام أداة تعقب المشكلات عندما تكون واثقًا من وجود خطأ في المكتبة يمكنك إعادة إنتاجه باستمرار باستخدام مثال يمكنك مشاركته.
شكر!