React: componentDidReceiveProps من فضلك

تم إنشاؤها على ٢٧ فبراير ٢٠١٥  ·  94تعليقات  ·  مصدر: facebook/react

أود أن أطلب بكل تواضع ربط componentDidReceiveProps ، غالبًا ما أرغب في القيام بشيء ما على كل من componentWillMount و componentWillReceiveProps ، ولكن نظرًا لأن this.props لم يتم تعيينه بعد ، فأنا مجبر على تمرير الدعائم بدلاً من القراءة مباشرة من this.props .

قبل الخطاف الجديد

componentWillMount() {
  this.setup(this.props.id);
}

componentWillReceiveProps(next) {
  this.setup(next.id);
}

setup(id) {
  UserActions.load(id);
}

بعد خطاف جديد

componentWillMount() {
  this.setup();
}

componentDidReceiveProps() {
  this.setup();
}

setup() {
  UserActions.load(this.props.id);
}

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

يرجى التفكير في إضافة componentDidReceiveProps كخطاف للاستفادة من نفس الكود الذي يتم رفعه في componentWillMount دون إجبار كليهما على الدعائم الثابتة في جميع أنحاء المكون.

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

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

ال 94 كومينتر

لماذا لا setup(props) ؟

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

setup(props) {
  props = props || this.props
  UserActions.load(props.id)
}

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

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

+1 ، أجد هذا أيضًا محبطًا.

لم تعد تجد هذه مشكلة.

+1 ، أجد نفسي أيضًا أتجول في الدعائم كثيرًا. على غرار insin أعلاه ، كنت

setup(props = this.props) {
  doSomething(props);
}

لكن قررت أنه كان مضادًا للنمط بسبب الأخطاء الدقيقة التي يمكن أن تسببها إذا نسيت تمرير الدعائم الجديدة.

+1

أعتقد أن سبب عدم توفره هو أن this.props و this.state _ دائمًا_ يتوافقان مع القيم المعروضة. لا توجد طريقة لتنفيذ componentDidReceiveProps لا تؤدي إلى عرض آخر بدون كسر هذا القيد.

في معظم الأوقات ، إذا كنت تستخدم componentWillReceiveProps ، فأنت في الواقع تريد إما مكون ترتيب أعلى a la Relay ، أو شيء مثل الخطاف observe المقترح لـ React 0.14 .

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

+1

أريد أن أكون قادرًا على الرد على حدث الدعائم الجديد عندما يُرجع shouldComponentUpdate false ، لذلك في حالتي لا يمكنني استخدام componentDidUpdate .

+1

+1

ماذا عن componentWillMount و componentWillUpdate iammerrick

أريد أن أكون قادرًا على الرد على حدث props الجديد عندما يُرجع shouldComponentUpdate خطأ ، لذلك في حالتي لا يمكنني استخدام componentDidUpdate.

استخدم componentWillReceiveProps ؟

+1

+1 يساعد هذا في رمز DRY وتبسيط المنطق.

سأكون مفتوحًا لاستدعاء componentDidReceiveProps في الإعداد الأولي لجعل المثال الذي يبدأ هذا الموضوع مجرد وظيفة واحدة:

componentDidReceiveProps() {
  UserActions.load(this.props.id);
}

أفكار؟

componentWillReceiveProps() {
  setTimeout(()=> {
    if(this.isMounted()) {
      this.componentDidReceiveProps();
    }
  });
}
componentDidReceiveProps() {
  UserActions.load(this.props.id);
}

ماذا تعتقد؟

YourDeveloperFriend أعتقد أنه يعتمد على كيفية عمله بالنسبة إلى خطافات دورة الحياة الأخرى وتأخيرات العرض بسبب المهلات المتتالية على المكونات المتداخلة.

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

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

+1 من فضلك. قبيح جدا.

لا انا بخير. هناك حلول أفضل.

+1

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

عندما تفعل أشياء مثل

setup(id) {
    UserActions.load(id);
}

أدخلت الحالة إما في المكون أو (أسوأ بكثير) في الخارج. لماذا تحتاج في أي وقت إلى بيانات load() كل مرة يتلقى فيها المكون الدعائم (حتى أنها ليست مضمونة لتكون جديدة )؟ إذا كنت تقوم بالتحميل البطيء ، فالطريقة الصحيحة هي طلب البيانات بطريقة render() :

render() {
    var actions = UserActions.load(id);
    if (actions) // render
    else // show spinner or return null, etc.
}

UserActions.load = function(id) {
    if (data) return data;
    else // request the data, emit change on success
}

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

أخبرني ، @ me-andre ، لماذا لدينا كل من componentWillUpdate و componentWillReceiveProps ؟

في رأيي ، هذا لأنها تخدم أغراضًا مختلفة وكلاهما مفيد. تمامًا مثل هذين الاثنين ليسا متماثلين ، فإن render ليس هو نفسه الافتراضي componentDidReceiveProps لأنه يُستدعى لأسباب أخرى غير الدعائم الجديدة ؛ بالإضافة إلى ذلك ، لا يمكنك الوصول إلى الدعائم السابقة.

تكمن فائدة الدعائم السابقة في أنك لن تضطر إلى تحميل البيانات في كل مرة ؛ يمكن أن تكون مشروطة بناءً على الدعائم وما إذا كانت قد تغيرت.

من الواضح أن "[القبح] في عين الناظر" ، لأن إضافة طريقة دورة حياة مناسبة تبدو وكأنها حل أكثر نظافة بالنسبة لي.

ربما هناك طريقة أخرى للنظر إلى هذا ...

لنفترض أن الأهداف الرئيسية هنا هي:

(1) تقليل الخطأ البشري - لقد نسيت تمرير المعلمات أو استخدام props = props || this.props مرة أخرى
(2) لتقليل الشفرة المعيارية غير ذات القيمة المضافة - لماذا تكتب شيئًا غير ضروري
(3) لتقليل العبء المعرفي لمحاولة تحديد طرق دورة الحياة التي يجب استخدامها - لماذا أحتاج إلى التفكير في هذا النوع من الأشياء ، لماذا أستمر في استخدام أساليب مختلفة قليلاً اعتمادًا على ما أشعر به في ذلك اليوم ، إلخ.

لذلك ربما تكون مساحة الحل حول تبسيط استخدام React وواجهة برمجة تطبيقات React نفسها لتحقيق هذه الأهداف.

إذا كنت تفكر في المشكلة مع وضع هذه الأهداف في الاعتبار ، فربما يمكن دمج بعض طرق دورة الحياة وإذا كنت مهتمًا بمعرفة أنها تهيئة مقابل تحديث ، فيمكنك معرفة ذلك من خلال التوقيع / الوسائط. على سبيل المثال: beforeRender(prevProps, prevState) أو update(prevProps, prevState) .

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

robyoder ، الإجابة المختصرة عن سبب وجود كل من componentWillUpdate و componentDidReceiveProps هي أن هناك فرقًا كبيرًا بينهما. إنها متشابهة بالطبع ، ولكن بشكل أساسي في كونها مسبوقة بـ componentWill .

| | تغيرت الدولة | المكون لم يتم تحديث |
| --- | --- | --- |
| componentWillUpdate () | نعم | لا |
| componentWillReceiveProps () | لا | نعم |

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

ومع ذلك ، فإن componentDidReceiveProps() كما تم وصفه في هذا الموضوع لا يمثل أي حالة أو شرط مكون ولا يمنح حق الوصول إلى أي شيء لا يقدمه componentWillReceiveProps() . إنه يضيف فقط سكرًا نحويًا بسيطًا قد يبدو أو لا يبدو مفيدًا أو أسهل - هذا تفضيل شخصي ، وليس مطلبًا تقنيًا . وهذا هو بالضبط سبب عدم إضافتها: إنها ذاتية. أنت تقول إن المجادلات العابرة قبيحة - لكنك قلت أيضًا "[القبح] في عين الناظر". بالنسبة لي يبدو أنك أجبت بنفسك.

@ me-andre ربما ترد علي (kmalakoff) و @ robyoder في نفس الوقت. أو ربما لا ، لكنني سأنتهز هذه الفرصة لدفع المناقشة إلى الأمام ...

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

دعنا نذهب من خلال التمرين ....

لنفترض أن هذا الموضوع يتم اتباعه و + 1-ed لأن هناك شيئًا مهمًا بالنسبة له ولنفترض أن إضافة componentDidReceiveProps ليست فكرة جيدة لأنها تزيد من مساحة سطح API.

مع الأخذ في الاعتبار الجدول والأهداف الثلاثة التي طرحتها ، هل لدى أي شخص أي أفكار لتبسيط واجهة برمجة التطبيقات و / أو طريقة أخرى لمنح الأشخاص في هذا الموضوع ما يرغبون فيه وعدم توسيع واجهة برمجة التطبيقات (ربما حتى تقليلها / تبسيطها) )؟

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

المشكلة الأولى التي تتحدث عنها هي أن طرق دورة الحياة تأخذ حججًا مختلفة. حسنًا ، هذا طبيعي تمامًا - يخدمون أغراضًا مختلفة. يأخذ componentWillReceiveProps الدعائم ليس لأن القمر كان مكتملًا عند إضافة هذه الطريقة - ولكن لأنه يتعلق بتلقي الدعائم التي لم يتم تعيينها بعد للمكون. يتم تمرير props فقط في الطرق التي (قد) تختلف فيها عن this.props . هذا في الواقع تلميح وليس مشكلة.
المشكلة رقم 3 هي أنه من الصعب عليك أن تقرر أسلوب رد الاتصال الذي تريد استخدامه. حسنًا ، هذه ليست مشكلة حقًا حتى يكون للطرق التي أتحدث عنها أعلاه نفس التوقيع. بمجرد أن يكون لديك كل من state و this.state و props و this.props وهي متساوية (قراءة بلا معنى) في معظم الطرق ، فإنك تتورط في الخيارات الاحتياطية و بدائل.
المشكلة رقم 2 تتعلق بالشفرة المعيارية ... حسنًا ، React مكتبة رقيقة - وهي جميلة وسهلة وصارمة بسبب ذلك. إذا كنت ترغب في عمل غلاف من شأنه أن يبسط حياتنا ويقلل من كمية الكود الذي نكتبه كل يوم - فلماذا لا نفعل ذلك؟ انشرها على أنها npm الخاصة بك والتي تعتمد على react وقد انتهيت.

بخصوص "هناك عدد كبير جدًا من طرق دورة الحياة" - ليس بعد ولن يحدث أبدًا إذا توقفت عن طلب عمليات رد اتصال جديدة ليس لديك حاجة فنية لها. الحاجة التقنية هي عندما تقوم بتنفيذ مكون معقد وفي منتصف العمل تدرك أنه لا توجد طريقة على الإطلاق للقيام بذلك دون بعض الاختراق القبيح. يتعلق الأمر "بتشغيل طريقة DOM صعبة ، أحتاج إلى شيء ما ليتم استدعاؤه في الوقت الذي يقوم فيه المكون بـ X ولكن لا توجد مثل هذه الطريقة ولا يمكنني إضافة واحدة ، لذلك أستخدم setTimeout وآمل ألا تهبط في وقت أبكر مما أحتاجه". ليس عندما تقول "أوه ، لقد سئمت من كتابة الدعائم = this.props".

وهناك شيئ اخر...
في تطبيق React المصمم جيدًا ، لا تحتاج إلى معظم الأساليب التي نتحدث عنها أو نادرًا ما تستخدمها. getInitialState ، componentWillMount ، componentWillUnmount يكفي 99٪ من الوقت. في مشروعي الحالي وهو تطبيق تجاري كبير نسبيًا ، يتم استخدام componentWillReceiveProps مرتين في جميع أنحاء التطبيق. لن أستخدمه على الإطلاق ، لكن البيئة (قراءة المتصفح) غير كاملة - معالجة بعض الأشياء "ذات الحالة في حد ذاتها" مثل scrollTop أو الاعتماد على حسابات التخطيط للمستقبل render s يتطلب المزامنة اليدوية بين انتقالات props وتغييرات DOM. ولكن في معظم الحالات "العادية"، أنت فقط لا تحتاج إلى معرفة متى props يحدث الانتقال.

@ me-andre استنادًا إلى خبرتي في العمل مع React ، أعتقد أن هناك مجالًا لتحسين / تبسيط واجهة برمجة التطبيقات. أنا لست وحدي وهذا هو سبب إثارة هذه المشكلة في المقام الأول ويتم إجراء +1 لها.

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

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

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

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

@ me-andre أعتقد أننا نفهم موقفك وخط حجتك جيدًا الآن. شكرا لك! قد تكون محقًا في أن واجهة برمجة التطبيقات جيدة بالفعل كما ستحصل ، ولكن هناك أيضًا إمكانية تحسينها.

هل يمكن لشخص ما تقديم قضية لتغيير واجهة برمجة التطبيقات؟ على سبيل المثال تقديم تحليل مقارن لمختلف الخيارات (إضافة componentDidReceiveProps مقابل دمج / تبسيط واجهات برمجة التطبيقات مقابل عدم التغيير)

كان فريق React يراقب المشكلة ونناقشها داخليًا. من حيث المبدأ ، أميل دائمًا إلى التخلص من مساحة سطح واجهة برمجة التطبيقات ، لذلك أجد نفسي أميل إلى حجج @ me-andre. ومع ذلك ، يشير فريقنا أحيانًا بمودة إلى componentDidReceiveProps أنه "طريقة دورة الحياة المفقودة" ، وهناك مناقشات جادة حول إمكانية إضافتها. الشيء المهم هو أننا نقوم بتمكين أفضل الممارسات دون تحفيز الممارسات السيئة.

ما سيكون أكثر فائدة لنا (أو على الأقل لي) هو أن يكون لدينا فهم قوي لسبب رغبة الناس في طريقة دورة الحياة هذه. ما الذي تحاول القيام به في دورة الحياة هذه التي لا تغطيها طرق دورة الحياة الأخرى بشكل كافٍ؟ لماذا قد يرغب شخص ما في تنفيذ UserActions.load(id); ضمن componentDidReceiveProps بدلاً من العرض الداخلي كما هو مقترح في https://github.com/facebook/react/issues/3279#issuecomment -163875454 (يمكنني التفكير في سبب ، لكنني أشعر بالفضول ما هي أسبابك)؟ هل هناك أي حالات استخدام بخلاف بدء تحميل البيانات بناءً على الدعائم؟

jimfb أعتقد أن componentDidReceiveProps هو بالضبط ما أحتاجه وأن الأساليب الأخرى غير مناسبة ، لكن قد أكون مخطئًا. سأشرح بسعادة حالة الاستخدام الخاصة بي.

لدي مسار في react-router يبدو كالتالي:

    <Route path="/profile/:username" component={ProfilePage} />

أحتاج إلى جلب البيانات للملف الشخصي من مصدر خارجي ، ولكي أقوم بذلك بشكل صحيح ، أحتاج إلى تقديم طلب HTTP بالطريقة componentDidMount .

لسوء الحظ ، عندما أتنقل من ملف تعريف إلى آخر ، لا يستدعي React Router طريقة المُنشئ أو طريقة componentDidMount مرة أخرى (بالطبع قد يكون هذا خطأ ولكنني سأفترض أنه ليس كذلك الآن) .

فكرت في إصلاح هذا باستخدام componentDidReceiveProps النظري. لسوء الحظ ، لم يكن موجودًا بعد ، ولن يلبي componentWillReceiveProps احتياجاتي.

أي مؤشرات على هذا سيكون موضع تقدير كبير.

حدسي هو أن componentDidReceiveProps هو بالضبط ما أحتاجه.

@ shea256 هل يمكنك توضيح سبب عدم تلبية componentWillReceiveProps لاحتياجاتك؟

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

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

يجب أن يؤدي كل من تركيب واستلام الدعائم الجديدة إلى بدء دورة التحميل نفسها ، لذا فإن componentDidMount و componentWillReceiveProps هو المكان المناسب لاستدعاء وظيفة التحديث. render على معلومات عما إذا كان عنصرًا جديدًا أم لا ، وعلى أي حال ، فإن setState من التقديم هي no-no.

لذلك ، لدي وظيفة واحدة تقوم بالتحميل. لكن عليّ تمرير props كمعامل وتجنب بحذر استخدام this.props التي انتهت صلاحيتها لـ componentWillReceiveProps . ينتهي هذا الأمر حتمًا بالتسبب في أخطاء حيث يتعين عليك أن تتذكر استخدام الدعائم التي تم تمريرها أو تحصل على أخطاء خفية وراء ظهور التغييرات. وتكون تواقيع جميع الأساليب المتضمنة أكثر تعقيدًا حيث يلزم تمرير الدعائم.

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

jimfb أحتاج إلى الحصول على اسم المستخدم الجديد في routeParam وباستخدام componentWillReceiveProps لم أحصل عليه بعد.

أحتاج إلى تقديم طلب HTTP لتحميل بيانات الملف الشخصي من مصدر خارجي (لا يتم تخزين البيانات محليًا).

ويمكنني تحديث المكون الخاص بي في طريقة العرض ولكن يبدو أنه متسخ بعض الشيء:

constructor(props) {
  super(props)

  this.state = {
    id: this.props.routeParams.id,
    profile: {}
  }
}

componentDidMount() {
  this.getProfile(this.state.id)
}

render() {
  if (this.props.routeParams.id !== this.state.id) {
    this.getProfile(this.props.routeParams.id)
  }

  return (
    <div>
      <div className="name">
       {this.state.profile.name}
      </div>
    </div>
  )
}

كتب grassick :

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

نعم ، هذه بالضبط حالة الاستخدام الخاصة بي.

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

احسنت القول.

@ shea256 ألا يتم ذلك باستخدام componentWillReceiveProps بدلاً من ذلك؟

constructor(props) {
  super(props)

  this.state = {
    id: this.props.routeParams.id,
    profile: {}
  }
}

componentDidMount() {
  this.getProfile(this.state.id)
}

componentWillReceiveProps(nextProps) {
  let { id } = nextProps.params
  if(id !== this.state.id) {
    this.getProfile(id, (profile) => {
      this.setState({ id: id, profile: profile })
    })
  }
}

render() {
  return (
    <div>
      <div className="name">
       {this.state.profile.name}
      </div>
    </div>
  )
}

كتب grassick :

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

كتب grassick :

لا يحتوي العرض على معلومات حول ما إذا كان عنصرًا جديدًا ، وعلى أي حال ، فإن setState من التقديم هي no-no.

مجرد spitballing هنا: إذا تم استدعاء componentDidUpdate عند العرض الأولي (بالإضافة إلى عمليات العرض اللاحقة) ، فهل سيحل ذلك حالة الاستخدام الخاصة بك؟ يمكنك التحقق مما إذا تم تغيير الدعائم وتحميل جميع بياناتك componentDidUpdate ، أليس كذلك؟ وفي العرض ، ستعرف أنك كنت تقوم بتحميل البيانات إذا كان this.state.profileName != this.props.profileName . هل سيكون هذا البديل كافيًا لحالات الاستخدام الخاصة بك؟


هل توجد أي حالات استخدام لدى الأشخاص لا تتضمن بيانات تحميل مكونات تستند إلى الدعائم؟

calmdev hm ، أعتقد أنك على حق. سأحاول ذلك.

ربما jimfb ، على الرغم من أنني حاولت استخدام componentDidUpdate واعتقدت أنه لم ينجح. يمكنني إلقاء نظرة أخرى.

ويبدو أنه يمكنني إجراء فحص على this.state.profileName != this.props.profileName ولكن هذا يبدو أيضًا وكأنه اختراق ، أليس كذلك؟ في هذه المرحلة ، إذا انتهى عمل componentWillReceiveProps(nextProps) ، فأنا أفضل ذلك فقط. الآن ، ما يزعجني هو عدم وجود تناظر مع componentDidMount . هل يمكنني استخدام componentWillMount بدلاً من componentDidMount ؟

أشعر فقط أن دورة الحياة بأكملها يمكن أن تكون أكثر نظافة.

@ shea256 ، لدي سؤال لك ... هل قرأت README لـ React؟
لا أشعر بالراحة لقول ذلك ، ولكن إذا لم يكن الأمر كذلك ، فمن المحتمل ألا تطلب ميزات جديدة للأداة التي لست على دراية بها. بالنسبة لي هذا يبدو ... سخيف.
"هل يمكنني استخدام componentWillMount بدلاً من componentDidMount ؟"
لا ، لا يمكنك ذلك لأنه كما هو مذكور في الملف التمهيدي ، يتم استدعاء componentWillMount قبل أن يصل المكون الخاص بك إلى DOM و componentDidMount - بعد ذلك. حسنًا ، يمكنك بالتأكيد استبدال طريقة بأخرى وسيؤدي ذلك إلى كسر الكود الخاص بك. السبب وراء وجود طريقتين هنا ليس الجماليات (اقرأ "التناظر"). ذلك لأننا قد نحتاج إلى طريقة واحدة للقيام بتحضير قبل العرض والأخرى لبعض استعلامات / معالجة DOM الأولية بعد التصيير الأول. ولكن حتى هذا أمر غريب بالنسبة لمكوِّن متوسط ​​في React. عادة ، لا تحتاج فقط إلى الوصول إلى DOM يدويًا.
"ويبدو أنه يمكنني تمامًا إجراء فحص على this.state.profileName! = this.props.profileName ولكن هذا يبدو أيضًا وكأنه اختراق ، أليس كذلك؟"
نعم ، نهجك بالكامل هو اختراق. ومن قال لك أن componentDidReceiveProps سيضمن تغيير props ؟ لا شيء سيفعل ذلك ما لم تحدد shouldComponentUpdate .
هذه هي الطريقة التي يعمل بها React.

@ me-andre نشكرك على القفز ولكنك تكون قاسيًا جدًا على ذوقي. كما أنني لا أعتقد أنك فهمت أسئلتي. أنا على دراية كاملة بما يفعله componentWillMount و componentDidMount . سأنتظر ردjimfb .

@ shea256 ،
"كما أنني لا أعتقد أنك فهمت أسئلتي."
هل يمكنك الإشارة إلى المكان الذي أفتقد فيه النقطة عندما أجيب على أسئلتك؟
أيضًا ، هل يمكنك توضيح ما تحاول أن تسأل عنه.
أيضًا ، نحن هنا ليس لمناقشة الشخصيات أو الأذواق. هذا ليس حديث خاص ، ولا هو دعم تقني. هذا ليس حتى موقعًا لتبادل المكدس حيث يمكنك أن تتوقع أن يرشدك أحد خلال بعض مجالات المعرفة.
غالبًا ما أتحدث في اللقاءات المحلية وكذلك المؤتمرات الدولية حول React (وليس فقط) وأنا منفتح جدًا على مشاركة المعرفة - متى وأينما كان ذلك مناسبًا. يمكنك دائمًا الاتصال بي مباشرة عبر البريد الإلكتروني أو سكايب.

بخصوص مشكلتك في تحميل بيانات الملف الشخصي. أنت تحاول حل مشكلة تطبيق نهج الأمر الكلاسيكي على إطار وظيفي المنحى. وجهة النظر في React هي دالة للدعامات والحالة والبيئة. مثل function(state, props) { return // whatever you've computed from it } (لكن الأمور تصبح أكثر تعقيدًا قليلاً في العالم الحقيقي - وإلا لما وجدت React على الإطلاق). على الرغم من أننا نحصل على مكونات وظيفية خالصة في 0.14 أن وظيفة الإدخال هذه بالنسبة لمعظم المكونات

هذا يعني أنك تبدأ الكتابة من render() وتفترض أن أدواتك محدثة دائمًا ولا تهتم بما إذا كان props قد تم تغييره أم لا ، وكم مرة وأين . يمكن تنفيذ حالتك بالطريقة التالية:

// profile-view.js

var React = require('react');

module.exports = React.createClass({
    contextTypes: {
        app: React.PropTypes.object.isRequired
        // another option is var app = require('app')
        // or even var profiles = require('stores/profiles')
    },
    componentWillMount() {
        var {app} = this.context; // another option is to require('app')
        app.profiles.addListener('change', this.onStoreChange);
    },
    componentWillUnmount() {
        var {app} = this.context; // another option is to require('app')
        app.profiles.removeChangeListener('change', this.onStoreChange);
    },
    onStoreChange() {
        this.forceUpdate();
    },
    render() {
        var {app} = this.context;
        var profile = app.profiles.read(this.props.routeParams.id);
        if (profile) { // profile's been loaded
            return <div>{profile.name}</div>;
        } else { // not yet
            return <div>Loading...</div>;
        }
    }
});

// profiles-store.js
// app.profiles = new Profiles() on app initialization

var EventEmitter = require('events');
var {inherits} = require('util');

module.exports = Profiles;

function Profiles() {
    this.profiles = {};
}

inherits(Profiles, EventEmitter);

Profiles.prototype.read = function(id) {
    var profile = this.profiles[id];
    if (!profile) {
        $.get(`profiles/${id}`).then(profile => {
            this.profiles[id] = profile;
            this.emit('change');
        });
    }
    return profile;
};

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

@ me-andre من المحتمل أن يكون الأمر يستحق التخفيف من لغتك قليلاً ، حيث يمكن أن تكون تصادمية قليلاً على الرغم من أنك تحاول فقط المساعدة. نريد إنشاء مجتمع ترحيبي للجميع ؛ كنا جميعًا مبتدئين في وقت ما. على الرغم من أنك محق في بعض النقاط الخاصة بك حول واجهة برمجة التطبيقات / التصميم ، فإن حقيقة أن الكثير من الأشخاص يقومون بإجراء 1+ للمشكلة هو مؤشر على وجود خطأ ما ، لذلك يجب أن نحاول فهم ماذا / لماذا يريد الناس ذلك دورة الحياة. ربما تكمن المشكلة في أننا لا نتواصل بشكل كافٍ حول كيفية كتابة المكونات بشكل صحيح (الوثائق) ، أو ربما تحتاج واجهة برمجة تطبيقات React إلى تغيير - وفي كلتا الحالتين ، يجدر فهم الشكاوى / الأسئلة / التعليقات هنا.

يقوم @ shea256 this.state.profileName != this.props.profileName بالتحقق لمعرفة ما إذا كانت الحالة الداخلية (ما الذي يعرضه المكون) تطابق ما يطلب الأصل من المكون عرضه. هذا هو تعريف "المكون يتم تحديثه" أو "المكون محدث" ، لذلك لا أرى أنه اختراق. على الأقل ، لا توجد في المقام الأول فكرة "إطلاق طلب تحديث البيانات عندما تتغير الخاصية وتؤدي حالة تعيين في رد الاتصال".

@ shea256 لكي نكون واضحين: دورة الحياة المقترحة هذه لن تمكنك من القيام بأي شيء لا يمكنك فعله اليوم مع دورات الحياة الحالية. من شأنه فقط أن يجعله أكثر ملاءمة. كما ذكر آخرون ، ما تحاول القيام به ممكن مع دورات الحياة الحالية (هناك مجموعات متعددة من دورات الحياة التي من شأنها أن تسمح لك بتحقيق هدفك). إذا كنت تحاول "جعله يعمل" ، فسيكون StackOverflow مكانًا أفضل للمناقشة. تحاول مشكلة github هذه فهم الحاجة إلى componentDidReceiveProps حيث صلتها ببيئة عمل المطور.

ومن أخبرك أن componentDidReceiveProps سيضمن تغيير الدعائم؟

@ me-andre صحيح هنا. معظم طرق دورة الحياة لا تضمن في الواقع أن شيئًا ما قد تغير ؛ إنها تشير فقط إلى أن شيئًا ما قد تغير. لهذا السبب ، تحتاج دائمًا إلى التحقق مما إذا كان previous === next إذا كنت ستفعل شيئًا مثل تقديم طلب http. يبدو أن مجموعة من الأشخاص في هذا الموضوع يفترضون أن قيمتها قد تغيرت لمجرد تشغيل طريقة دورة الحياة.

كتب @ me-andre:

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

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

الكل: هل هناك أي حالات استخدام لـ componentDidReceiveProps بخلاف "تحميل البيانات بشكل غير متزامن استجابة لتغيير خاص"؟

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

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

jimfb كتب:

@ me-andre من المحتمل أن يكون الأمر يستحق التخفيف من لغتك قليلاً ، حيث يمكن أن تكون تصادمية قليلاً على الرغم من أنك تحاول فقط المساعدة. نريد إنشاء مجتمع ترحيبي للجميع ؛ كنا جميعًا مبتدئين في وقت ما. على الرغم من أنك محق في بعض النقاط الخاصة بك حول واجهة برمجة التطبيقات / التصميم ، فإن حقيقة أن الكثير من الأشخاص يقومون بإجراء 1+ للمشكلة هو مؤشر على وجود خطأ ما ، لذلك يجب أن نحاول فهم ماذا / لماذا يريد الناس ذلك دورة الحياة. ربما تكمن المشكلة في أننا لا نتواصل بشكل كافٍ حول كيفية كتابة المكونات بشكل صحيح (الوثائق) ، أو ربما تحتاج واجهة برمجة تطبيقات React إلى تغيير - وفي كلتا الحالتين ، يجدر فهم الشكاوى / الأسئلة / التعليقات هنا.

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

jimfb كتب:

@ shea256 this.state.profileName! = يتم التحقق من this.props.profileName لمعرفة ما إذا كانت الحالة الداخلية (ما يعرضه المكون) تطابق ما يطلب الأصل من المكون عرضه. هذا هو تعريف "المكون يتم تحديثه" أو "المكون محدث" ، لذلك لا أرى أنه اختراق. على الأقل ، لا توجد في المقام الأول فكرة "إطلاق طلب تحديث البيانات عندما تتغير الخاصية وتؤدي حالة تعيين في رد الاتصال".

نعم ، هذا يبدو معقولا.

jimfb كتب:

@ shea256 لكي نكون واضحين: دورة الحياة المقترحة هذه لن تمكنك من القيام بأي شيء لا يمكنك فعله اليوم مع دورات الحياة الحالية. من شأنه فقط أن يجعله أكثر ملاءمة. كما ذكر آخرون ، ما تحاول القيام به ممكن مع دورات الحياة الحالية (هناك مجموعات متعددة من دورات الحياة التي من شأنها أن تسمح لك بتحقيق هدفك). إذا كنت تحاول "جعله يعمل" ، فسيكون StackOverflow مكانًا أفضل للمناقشة. تحاول مشكلة github هذه فهم الحاجة إلى componentDidReceiveProps من حيث صلتها ببيئة عمل المطور.

أنا أتفق كثيرا مع هذا. لم أنشر حالة الاستخدام الخاصة بي لتلقي المساعدة بشأنها. لقد قمت بالنشر لتقديم نظرة ثاقبة حول سبب اعتقادي أن componentDidReceiveProps سيكون مفيدًا.

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

jimfb كتب:

@ me-andre صحيح هنا. معظم طرق دورة الحياة لا تضمن في الواقع أن شيئًا ما قد تغير ؛ أنها تشير فقط إلى أن شيئًا ما قد تغير. لهذا السبب ، تحتاج دائمًا إلى التحقق مما إذا كان السابق === التالي إذا كنت ستفعل شيئًا مثل تقديم طلب http. يبدو أن مجموعة من الأشخاص في هذا الموضوع يفترضون أن قيمتها قد تغيرت لمجرد تشغيل طريقة دورة الحياة.

أنا لا أقوم بهذا الافتراض. لقد تركت الشيك ولكني الآن أستخدمه. ولكن في أسوأ الأحوال ، سيتم تشغيل طلب إضافي.

jimfb كتب:

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

ربما. سأفكر أكثر في هذا الأمر.

componentDidReceiveProps مفيدًا لحالة استخدام محددة لدي.

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

عندما تتغير أدواتي لأنني انتقلت إلى معرّف عنصر مختلف في نفس المسار ، أحتاج إلى الاستعلام عن متجري مرة أخرى أو سيتعطل المكون الخاص بي بالحالة من العنصر السابق في المتجر.

في الوقت الحالي ، عندما يتم استدعاء componentWillReceiveProps ، أتحقق لمعرفة ما إذا تم تغيير أي من معلمات المسار الخاصة بي ، وإذا حدث ذلك ، فأنا اتصل بـ updateItemState. ولكن نظرًا لأن الدعائم لم تتغير فعليًا بعد ، يجب علي الآن تمرير الدعائم إلى طريقتي.

this.updateItemState( nextProps );

updateItemState( props ) {
    props = props || this.props;

    this.setState( {
        item: this.getItemState( props )
    } );
}

getItemState( props ) {
    props = props || this.props;

    return this.ItemStore.get( props.params[ this.paramName ] );
}

سيصبح ببساطة

this.updateItemState();

updateItemState() {
    this.setState( {
        item: this.getItemState()
    } );
}

getItemState() {
    return this.ItemStore.get( this.props.params[ this.paramName ] );
}

أشعر أن هذه حالة استخدام معقولة.

@ akinnee-gl et al: إذا تم تشغيل componentDidUpdate بعد التثبيت الأولي بالإضافة إلى التحديثات ، فهل سيحل ذلك حالة الاستخدام؟

@ akinnee-gl ، إذا كنت تستخدم Flux ، فلن تحتاج إلى ضبط الحالة من متجر. ما لم يكن ذلك مستحيلًا تمامًا ، يجب أن تحافظ على الدولة في مكان واحد. عندما يتعلق الأمر بـ Flux ، فإن هذا المكان هو المتجر نفسه. عندما يصدر المتجر التغيير ، فأنت فقط forceUpdate() ثم في render() أنت read() متجرك.

"عندما تتغير أدواتي لأنني انتقلت إلى معرّف عنصر مختلف في نفس المسار ، أحتاج إلى الاستعلام عن متجري مرة أخرى أو سيتعطل المكون الخاص بي بالحالة من العنصر السابق في المتجر."

أبدا.

ألقِ نظرة: تحتاج إلى عرض عنصر معين من متجر وأي عنصر تريد تقديمه لك من props . إذا كان هذا هو مطلبك ، فيجب التعبير عنه في الكود بنفس الطريقة كما في الكلمات:

    var item = this.props.store.read(this.props.id);
    return <div>{item.name}</div>;

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

<FluxWrapper store={store} component={Component} id={this.props.routeParams.id} />

var FluxWrapper = React.createClass({
    componentWillMount() {
        this.props.store.addListener('change', this.onStoreChange);
    },
    componentWillUnmount() {
        this.props.store.removeListener('change', this.onStoreChange);
    },
    onStoreChange() {
        this.forceUpdate();
    },
    render() {
        var Component = this.props.component;
        return <Component {...this.props} />;
    }
});

var Component = React.createClass({
    render() {
        var item = this.props.store.read(this.props.id);
        return <div>{item.name}</div>;
    }
});

شاهد كيف يمكن أن تصبح مكوناتك صغيرة إذا كنت تستخدم React بشكل صحيح.

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

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

نهج مثير للاهتمام. سأضع الامر في بالي. تقول جميع المستندات الرسمية لـ React أن تحافظ على وظائف العرض الخاصة بك نقية (بمعنى أنه يجب عليك فقط الوصول إلى الخاصيات والحالة في عمليات التصيير). تُظهر جميع أمثلة Flux حالة الإعداد من المتجر.

jimfb المشكلة في componentDidUpdate هي أنه استدعى لسبب آخر غير تغيير

@ akinnee-gl componentWillReceiveProps قد يتم استدعاءه أيضًا لأسباب أخرى غير تغيير الدعائم (انظر: https://github.com/facebook/react/issues/3279#issuecomment-164713518) ، لذلك يجب عليك التحقق لترى إذا تغيرت الخاصية بالفعل على أي حال (بغض النظر عن دورة الحياة التي تختارها). أيضًا ، إذا كنت تقوم بالفعل ببيانات غير متزامنة ، فستنتظر حلقة الحدث التالية قبل أن يتم تشغيل رد الاتصال على أي حال ، لذلك لا أعتقد أنه سيكون من المهم إذا تم استدعاء وظيفتك على الفور قبل / بعد تقديم وظيفة ، أليس كذلك؟

jimfb حسنًا ، إذا كان العنصر الذي تشير إليه

@ me-andre يعجبني حقًا أسلوبك في القراءة فقط من المتجر أثناء العرض. يبدو أنه يبسط الكود. أنا قلق من أنك تفقد بعض الكفاءة من خلال القيام بذلك بالرغم من ذلك. تفقد القدرة على التحكم في التحديث عبر shouldComponentUpdate ، وتتطلب منك إضافة مكون FluxWrapper الإضافي الذي ذكرته. أي أفكار في ذلك؟

لقد كنت أراقب المناقشة وأرغب في إعادة طرح الخيار الثالث: (1) واجهة برمجة التطبيقات رائعة كما هي ، (2) تحتاج إلى componentDidReceiveProps ، و (3) ربما توجد واجهة برمجة تطبيقات أبسط.

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

يمكن أن تستند واجهة برمجة التطبيقات المبسطة إلى المبادئ التالية:

(أ) تبسيط بنية الكود / تقليل الصيغة المعيارية
(ب) إبقاء الدعائم (المدخلات) منفصلة عن الحالة (داخلية)

السبب الرئيسي لـ (أ) هو أنني أجد نفسي أكتب نموذجًا غير ذي قيمة مضافة. مثال:

componentWillMount() { this.actuallyCheckThePropsAndMaybeDoSomething(); }
componentWillReceiveProps(nextProps) { this.actuallyCheckThePropsAndMaybeDoSomething(nextProps); }

actuallyCheckThePropsAndMaybeDoSomething(props) {
  props = props || this.props;

  let relatedProps1 = _.pick(props, KEYS1);
  if (!shallowEqual(this.relatedProps1, relatedProps1) { // changed
   this.relatedProps1 = relatedProps1;

   // do something
  }

  let relatedProps2 = _.pick(props, KEYS2);
  if (!shallowEqual(this.relatedProps1, relatedProps2) { // changed
   this.relatedProps2 = relatedProps2;

   // do something else
  }
}

أفضل فعلًا القيام بما يلي وليس لدي مسار رمز منفصل لأول مرة مقابل التغيير:

propsUpdated(prevProps) {
  if (!shallowEqual(_.pick(prevProps || {}, KEYS1), _.pick(this.props, KEYS1)) { // changed
   // do something
  }

  if (!shallowEqual(_.pick(prevProps || {}, KEYS2), _.pick(this.props, KEYS2)) { // changed
   // do something
  }
}

بالنسبة إلى (B) ، فإن المشكلة الرئيسية في componentDidUpdate التي تم ذكرها للتو هي أنه يمكنك تشغيل استدعاءات طريقة متكررة إذا قمت بتعيين الحالة بسبب تغييرات الخاصية حيث يتم استدعاؤها لكل من props (المدخلات) والحالة (الداخلية). يبدو أن مسارات الشفرة هذه أفضل لأنها منفصلة لأن الدعائم يتم توفيرها من الخارج ويتم تعيين الحالة في الداخل ، على سبيل المثال. لقد جربت / فكرت في احتمال رابع updated(prevProps, prevState) (اسم مبسط لـ componentDidUpdate نظرًا لأن عددًا أقل من أساليب دورة الحياة قد يسمح بتسمية أقصر) باستخدام componentDidUpdate لتقليل الصيغة المعيارية ، لكني أجد نفسي غير راضٍ قليلاً عن الثانية المحتملة الزائدة عن الحاجة تحديث المكالمات وأن المنطق يبدو مستقلاً تمامًا في الممارسة.

استنادًا إلى البدء بمبادئ التصميم (أنا متأكد من وجود المزيد!) ، أتساءل عما إذا كان هناك شيء على غرار propsUpdated و stateUpdated يمكن أن يكون خيارًا ثالثًا محتملًا لهذه المناقشة ؟

kmalakoff ستحتاج دائمًا إلى التحقق مما إذا كانت العناصر قد تغيرت ، لأننا لن نتمكن من إخبارك بشكل قاطع بأن الدعائم قد تغيرت / لم تتغير (لأن Javascript لا تحتوي على أنواع قيم ولديها قابلية للتغيير).

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

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

أعتقد أنه يعني أنه لا توجد طريقة مضمنة وسريعة للتحقق مما إذا كان this.props === nextProps لأنه قد يكون أو لا يكون كائنين منفصلين.

{ a: 1 } === { a: 1 } ينتج خطأ لأنهما كائنان منفصلان ، لكن

var a = { a: 1 };
var b = a;
a === b

ينتج عنه صحيح لأن كلاهما في الواقع إشارة إلى نفس الكائن.

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

kmalakoff لا أريد الاستطراد في هذا الموضوع ، ولكن إليك جوهر لك: https://gist.github.com/jimfb/9ef9b46741efbb949744

TLDR: @ akinnee-gl صحيح تمامًا في شرحه (شكرًا!). مع التصحيح البسيط الذي لم نتمكن دائمًا من إجراء الفحص العودي على أي حال (حتى لو أردنا ذلك ، وكان الأداء لا يمثل مشكلة) ، لأنه لا توجد طريقة للتحقق بشكل متكرر من وظيفة رد الاتصال التي تم تمريرها كدعم.

دعنا نحافظ على هذا الموضوع على الرغم من: P.

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

إذا أراد أي شخص المشاركة في مجموعة واسعة من الحلول ، يرجى الانضمام إلينا هناك!

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

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

ألق نظرة على مكون صفحة ملفي الشخصي:

class ProfilePage extends Component {
  static propTypes = {
    fetchCurrentProfile: PropTypes.func.isRequired,
    currentProfile: PropTypes.object.isRequired
  }

  constructor(props) {
    super(props)
    this.state = { currentProfile: {} }
  }

  componentHasNewRouteParams(routeParams) {
    this.props.fetchCurrentProfile(routeParams.id)
  }

  componentWillMount() {
    this.componentHasNewRouteParams(this.props.routeParams)
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.routeParams.id !== this.props.routeParams.id) {
      this.componentHasNewRouteParams(nextProps.routeParams)
    }
    this.setState({
      currentProfile: nextProps.currentProfile
    })
  }

  render() {
    var profile = this.state.currentProfile
    return (
      <div>
        <h1>{ profile.name ? profile.name : null }</h1>
      </div>
    )
  }
}

عندما يتم تثبيت المكون ، فإنه لا يحتوي على بيانات ملف التعريف ويحتاج إلى تحميل ملف التعريف من مصدر خارجي.

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

الآن ، منذ أن تم تحديث الخاصيات ، تم استدعاء الوظيفة componentWillReceiveProps . لكننا لا نعرف سياق حدث تغيير الدعامة ، لذلك نحتاج إلى معرفة الدعائم (إن وجدت) التي تم تغييرها. نرى أن المعرف هو نفسه ، لذلك لا نحتاج إلى الاتصال بـ fetchCurrentProfile مرة أخرى. ثم نقوم بتحديث state.currentProfile حتى يعرف المكون إعادة العرض ببيانات الملف الشخصي الجديدة (نعم يمكنني القيام بذلك باستخدام الدعائم ، ولكن هناك سبب آخر لذلك لا أريد الخوض فيه هنا). في هذا الوقت ، يمكننا التحقق لمعرفة ما إذا كان props.currentProfile قد تغير قبل تحديث الحالة ، ولكن هذه ليست عملية مكلفة لذلك لا يهم إذا تحققنا.

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

عندما يعود الجلب الجديد ويرسل إجراء الإعادة ، يتم تحديث الخاصية currentProfile مرة أخرى ، ثم يتم تحديث الحالة ، ويعاد عرض المكون مع العرض الجديد.

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

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

الشيء الذي قد يساعد هنا ، على الرغم من ذلك ، هو المزيد من التوثيق حول دورة الحياة ، وأمثلة العمل ، وما إلى ذلك.

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

@ shea256 يبدو

لقد أوجزت المزيد من الأفكار في: https://gist.github.com/jimfb/9ef9b46741efbb949744 ، لكن ما زلت أشعر أننا يجب أن نكون قادرين على تبسيط واجهة برمجة التطبيقات لكتابة كود أقل ...

تخيل أن واجهة برمجة التطبيقات (api) سمحت لك بكتابة نفس الوظيفة ، ولكن مع صيغة معيارية أقل:

class ProfilePage extends Component {
  static propTypes = {
    fetchCurrentProfile: PropTypes.func.isRequired,
    currentProfile: PropTypes.object.isRequired
  }
  state = {currentProfile: {}}; // not material to example (babel-stage-1)

  // called both on init and update
  willReceiveProps(nextProps) {
    if (!this.props || (this.props.routeParams.id !== nextProps.routeParams.id)
      nextProps.fetchCurrentProfile(nextProps.routeParams.id)
  }

  render() {
    var profile = this.props.currentProfile;
    return (
      <div>
        <h1>{ profile.name ? profile.name : null }</h1>
      </div>
    )
  }
}

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

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

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

@ akinnee-gl ، فإن وجود تطبيق يتكون من العديد من المكونات الصغيرة أفضل بكثير من بعض المكونات الثقيلة لعدة أسباب:

  1. يرتبط هذا النهج بـ "مبدأ المسؤولية الواحدة"
  2. يمكنك أن ترى بوضوح أي مكون يفعل ماذا
  3. يمكنك بسهولة تكوين ميزات وتوسيع المكونات عن طريق الالتفاف
  4. الأساليب والخصائص لا تتعارض
  5. من الأسهل توسيع ميزة لأن أحد المكونات يحتوي على ميزة واحدة

فيما يتعلق بإشعارك بأن القراءة من متجر على كل عرض قد تكون غير فعالة ، فقد قمت بعمل فكرة توضح كيفية تنفيذ مكون وسيط للتخزين المؤقت: https://gist.github.com/me-andre/0ca8b80239cd4624e6fc

لقد قمت بتمرير آخر في المبادئ / الأهداف التي يمكن أن تؤدي إلى تحسين واجهة برمجة التطبيقات (نأمل أن تستند إلى طريقة الدعائم المستلمة كما هو مقترح في هذه المشكلة):

(أ) تبسيط بنية الكود / تقليل الصيغة المعيارية
(ب) إبقاء الدعائم (المدخلات) منفصلة عن الحالة (داخلية)
(ج) تسمح لطريقة للتحكم في عرض المكون
(د) تبسيط تسمية الأسلوب بناءً على افتراض التصنيف الفرعي للمكون
(هـ) قلل عدد طرق الدعائم إلى واحد لكل من التهيئة والتغييرات
(F) يجب أن تحتوي طريقة الدعائم على this.props بأحدث قيمة

هناك توضيحات حول بعضها في جوهرها.

kmalakoff وفقًا

kmalakoff العديد من النقاط التي https://github.com/reactjs/react-future/issues/40#issuecomment -142442124 و https://github.com/reactjs/react-future/issues/40#issuecomment - 153440651. هذه هي الخيوط المناسبة لإجراء تلك المناقشة. إذا كنت تبحث عن مناقشات عامة / شاملة حول التصميم / واجهة برمجة التطبيقات ، فمن المحتمل أن يكون الوسيط الصحيح هو https://discuss.reactjs.org/

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

من فضلك اسمعني ... الحد المعياري هو المشكلة التي يمكن أن تحلها طريقة دورة الحياة في هذه المشكلة بالنسبة لي.

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

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

kmalakoff يتم تحديد موضوع الموضوع من خلال العنوان وأول مشاركة. العنوان هو componentDidReceiveProps Please وليس lots of general ways to reduce boilerplate . يدور هذا الخيط حول تقليل النموذج المعياري على وجه التحديد من خلال إدخال طريقة دورة حياة محددة للغاية. هذه المناقشة وحدها هي بالفعل دقيقة بما فيه الكفاية ، دون تقديم مواضيع إضافية (مثل إعادة تسمية جميع الوظائف) التي تمت مناقشتها بالفعل في قضايا أخرى.

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

jimfb لماذا يطلب الناس componentDidReceiveProps ؟ سبب اهتمامي به هو تقليل الصيغة المعيارية المتعلقة بالدعائم . لست متأكدًا من كيفية توضيح ذلك بشكل أكثر وضوحًا حتى يتم سماعي وفهمي.

لقد طلبت المشكلات وحالات الاستخدام ، وقد ذكرت هذا على أنه مشكلة بالنسبة لي وأظهرت حالة استخدام أعلاه (ردًا على @ shea256) والتي تبدو على الموضوع ، وداخل النطاق ، ومن وجهة نظري ، مهمة لحلها هذه المسألة.

لقد وافقت على تأجيل توسيع النطاق ليشمل مشكلات / تحسينات واجهة برمجة التطبيقات العامة والإرادة. أعدك! :غمزة:

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

kmalakoff ، حسنًا ، لتقليل تصنيفًا فرعيًا أو تكوين مكونات أخرى. لا أحد يمنعك من تحديد طريقة مشتركة لجميع مكونات تطبيقك. توفر React قابلية توسعة ممتازة: يمكنك تحديد المكونات ككائنات أو وظائف أو فئات. يمكنك توسيع المكونات عن طريق التصنيف الفرعي أو الخلطات أو المصانع.

@ me-andre هذا خيار بالتأكيد إذا لم تؤد هذه المشكلة إلى تحسين واجهة برمجة التطبيقات.

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

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

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

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

ما هي حالات الاستخدام حيث تريد فقط تشغيل شيء ما عند تلقي دعائم جديدة (وليس عند استقبال الدعامة الأولي)؟

قد أفتقد شيئًا واضحًا هنا ولكني أحاول التوفيق بين وجهات نظر الأطراف المختلفة.

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

kmalakoff إذا تم تشغيل componentWillReceiveProps للمرة الأولى ، فهل يلبي ذلك معاييرك لتبسيط واجهة برمجة التطبيقات؟

لا يتم تشغيل componentWillReceiveProps عند التحميل ليس السبب في أن الناس يطلبون componentDidReceiveProps . يطلب الناس componentDidReceiveProps لأنهم كتبوا كل طرقهم للوصول إلى this.props . عندما يتم استدعاء componentWillReceiveProps ، يتم تمرير العناصر التالية ، ولكن this.props لم يتغير بعد ، مما يعني أنه يتعين علينا تمرير nextProps في جميع الطرق التي يتم استدعاؤها ردًا على componentWillReceiveProps بدلاً من تركها كما هي. لقد انتهى بنا الأمر مع طن من props = props || this.props وطنًا من تمرير props في كل وظيفة نسميها.

@ shea256 نقاط جيدة. يعد وجود مسارات رمز مختلفة للتهيئة مقابل التغييرات أحد الأسباب الجذرية لـ Prop boilerplate. السبب الجذري الآخر هو وجود تواقيع مختلفة للتعامل مع الدعائم مثل نقاط @ akinnee-gl.

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

آمل أن نتمكن من تحقيق المزيد:

قبل الخطاف الجديد

componentWillMount() {
  this.setup(this.props.id);
}

componentWillReceiveProps(next) {
  this.setup(next.id);
}

setup(id) {
  UserActions.load(id);
}

بعد خطاف جديد (منقح)

componentDidReceiveProps(prevProps) {
  UserActions.load(this.props.id);
}

أو إذا تعذر على UserActions.load التحقق من المعرف المحمّل حاليًا:

componentDidReceiveProps(prevProps) {
  if (!prevProps || (prevProps.id !== this.props.id))
    UserActions.load(this.props.id);
}

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

@ shea256 ، أحد الأسباب المحتملة لعدم تشغيل componentWillReceiveProps قبل العرض الأول هو أنه لا يوجد شيء مثل this.props في ذلك الوقت. ما تفعله عادة في componentWillReceiveProps هو مقارنة this.props[propName] بـ newProps[propName] . إن تشغيل الطريقة قبل العرض الأول سيجعلك أيضًا مضطرًا للتحقق من وجود this.props . علاوة على ذلك ، فإن المكون بالكامل غير مهيأ تمامًا في الوقت الذي يتلقى فيه props قبل التصيير الأولي ، ولا يحتوي حتى على state .

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

@ akinnee-gl ، السبب في عدم تقديم طريقة جديدة للوصول فقط إلى this.props عند التحديث هو أن لدينا مثل هذه الطريقة - تسمى render() . حتى أنه يتم استدعاؤه بعد إجراء شيك shouldComponentUpdate() - وهو عادةً مكان تقوم فيه بـ this.props !== newProps أو _.isEqual(this.props, newProps) إلخ.
إذا كنت تشعر أنه يجب أن يكون لديك طريقة منفصلة لبعض الإعداد ، فلماذا لا تقوم فقط بفئة فرعية لمكون React وتحديد طريقة render()

this.setup(this.props);
return this._render();

أنا فقط لا أرى كيف يبسط الأشياء في نظام React البيئي ، ولكن هذا ما تطلبه باستمرار.

@ me-andre إن فرضية هذه المشكلة لا تتمثل في أننا لا نستطيع تحقيق ما نريده باستخدام واجهة برمجة التطبيقات الحالية ولا أننا لا نستطيع التعامل مع واجهة برمجة التطبيقات الحالية في كود العميل. أساس هذه المشكلة هو أن واجهة برمجة تطبيقات React الحالية دون المستوى الأمثل وتحتاج إلى تحسين ؛ على سبيل المثال ، إذا توصلت إلى مبادئ لما ستبدو عليه واجهة برمجة التطبيقات المثلى (كما حاولت أعلاه) ، فإن واجهة برمجة تطبيقات React الحالية ستحرز نتائج في نطاق متوسط ​​المستوى لأنها دون المستوى الأمثل / ناقص في عدد من المجالات.

لسوء الحظ ، فإن توفير طرق في كود العميل للتغلب على React API لا يعالج الأسباب الجذرية للمشكلة ، ويحول النقاش بعيدًا عن معالجة المشكلات الأساسية ، ولن يؤدي إلى نقاش حول الحلول المحتملة لتحسين React API.

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

يجب أن تستهدف React 1.0 القمة وليس الوسط. يمكن أن تؤدي زيادة الإصدار الرئيسية إلى كسر التوافق مع الإصدارات السابقة ، لذا دعنا نذهب إلى أفضل واجهة برمجة تطبيقات ممكنة استنادًا إلى ما تعلمناه من كل هذه السنوات من استخدام الإصدار 0.x.

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

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

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

لسوء الحظ ، فإن توفير طرق في رمز العميل للتغلب على React API لا يعالج الأسباب الجذرية للمشكلة

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

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

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

أنت تخبر أن لديك هذه التجربة ، لقد رأيت مشاكل حقيقية ولديك بعض الحلول التي يمكنك مشاركتها. هذا هو بالضبط ما يمكن أن يحول هذا النقاش إلى "حقيقي" و "فعال". تم بناء React على مشاكل وتحديات حقيقية - وهذا هو السبب في أنها تحل مشاكل معمارية حقيقية وليس فقط "كيفية كتابة hello world في 3 أسطر".

@ me-andre أسمعك وخط حجتك واضح.

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

كيف تقيم React API الحالية حول الدعائم؟ (دعنا نقول باستخدام درجات الحروف: F إلى A +) ، لماذا ، وماذا ستفعل لتحسينه إذا كان أقل من A +؟

@ me-andre هل سنحت لك الفرصة لإعداد الترتيب والتحليل؟ أنا مهتم بسماع ما تعتقد أنه نقاط القوة والضعف والفرص مع واجهة برمجة التطبيقات الحالية.

+1

+1 من فضلك

ايوجد اي عمل في هذه المنطقه؟ أنا بحاجة إلى ComponentDidReceiveProps

لقد صنعت هذه المشكلة منذ أكثر من عام وكنت أستخدم React يوميًا منذ ذلك الحين. لم أعد أعتقد أن هناك حالة استخدام لـ componentDidReceiveProps تبرر زيادة واجهة برمجة التطبيقات.

AlexCppns ما الذي تحاول أن تفعله؟

iammerrick ، في الواقع لا بأس ، لقد أسأت فهم كيفية استخدام componentWillReceiveProps.

مناقشة ذات صلة: https://github.com/facebook/react/issues/7678

لقد واجهت هذا عدة مرات ، وما انتهى بي الأمر هو:

componentWillReceiveProps(nextProps) {
  if (this.props.foo !== nextProps.foo) this.needsUpdate = true;
}
componentDidUpdate() {
  if (this.needsUpdate) {
    this.needsUpdate = false;
    // update the dom
  }
}

انها ليست سيئة للغاية.

brigand ، ليست هناك حاجة لعلم - يمكنك مقارنة الدعائم ضمن componentDidUpdate() :

componentDidUpdate(prevProps) {
    let needsUpdate = prevProps.foo !== this.props.foo;
    // ...whatever
}

علاوة على ذلك ، يمكن كسر الحل بسهولة بواسطة shouldComponentUpdate() ، مما قد يمنع إعادة العرض.

أوه رائع ، شكرا!

jimfb أعتقد أن لدي حالة استخدام متزامنة أدناه. أعتقد أن componetDidReceiveProps سيكون مثاليًا لهذا.

  componentDidMount() {
    this._selectAll()
  }

  componentDidUpdate(prevProps) {
    let shouldUpdateSelected = (prevProps.recordTypeFilter !== this.props.recordTypeFilter) ||
      (prevProps.statusFilter !== this.props.statusFilter) ||
      (prevProps.list !== this.props.list)

    if (shouldUpdateSelected) { this._selectAll() }
  }

  _selectAll() {
    this.setState({ selectedIds: this._getFilteredOrders().map((order) => ( order.id )) })
  }

  _getFilteredOrders() {
    let filteredOrders = this.props.list

    // recordTypeFilter
    let recordTypeFilter = this.props.recordTypeFilter
    filteredOrders = _.filter(filteredOrders, (order) => {
        // somelogic
    })

    // statusFilter
    let statusFilter = this.props.statusFilter
    filteredOrders = _.filter(filteredOrders, (order) => {
        // somelogic
    })

    return filteredOrders
  }

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

  1. هذه هي حالة استخدام componentWillReceiveProps ، وليس componentDidUpdate . إذا قمت بالتبديل إلى componentWillReceiveProps ، فسيتم إعادة تصيير المكون الخاص بك مرتين أقل مع الحفاظ على نفس المنطق. بعد عام منذ أن تركت هذه المناقشة ، ما زلت أرى عدم وجود حالة استخدام لـ componentDidUpdate باستثناء الرد على تغييرات DOM.
  2. أفضل بكثير ، مع ذلك ، هو تجنب الخطافات على الإطلاق ونقل كل المنطق إلى طريقة render() / الترحيل إلى مكون عديم الحالة ، لأن this.state.selectedIds ليس حالة في الواقع. إنها محسوبة بحتة من الدعائم.

مرحبًا @ me-andre ، شكرًا على الوقت الذي استغرقته في الرد. لقد قرأت المناقشة في هذه الصفحة وأود أن أشكركم على المشاركة فيها.

نعم ، ليس هناك حاجة إلى componentDidReceiveProps ، لكن الأمور تبدو غامضة بدونها.
لقد قلت your component would re-render twice as less إذا استخدمت componentWillReceiveProps . لا يزال هذا لغزا بالنسبة لي.

لقد فكرت وجربت الشيئين اللذين اقترحتهما من قبل ، لكنني فشلت.

  1. لن تعمل componentWillReceiveProps لأن الوظيفة _getFilteredOrders() استدعاؤها من _selectAll() تحتاج إلى newProps.
  2. لم أستطع التفكير في طريقة لاشتقاق selectedIds بدون تخزينها في الحالة.

لقد قمت للتو بإنشاء مثال كامل من حالة الاستخدام الخاصة بي. لقد جعلت من السهل فهم الكثير قدر الإمكان.

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

chanakasan ، هيا ، هذا يبدو وكأنه رمز إنتاج. لن أقرأها كلها وأساعدك في مشروعك مجانًا.

ومع ذلك يمكنني توجيهك إلى الاتجاه الصحيح:

  1. يمكن لكل من componentWillReceiveProps() و componentDidUpdate() الوصول إلى الدعائم السابقة والتالية. هذا واضح من مستندات React الرسمية.
  2. من اللصق الكامل لشفرتك ، من الواضح الآن أنك تستخدم الحالة لتخزين المعرفات المحددة التي يمكن للمستخدم تبديلها. لا بأس من استخدام الحالة في ذلك الوقت ، ولكن لا يزال من الممكن أن يؤدي استخدام componentWillReceiveProps() إلى إعادة العرض مرتين أقل من ذلك. (لأن التجسيد سيحدث بعد componentWillReceiveProps() أي حال ، فإن setState() سيُحدِّث فقط حالة التصيير القادم).
  3. يرجى إلقاء نظرة على المستندات . وفر وقتك واحترم الآخرين.

@ me-andre أعتقد أنني أفهم وجهة نظرك حول componentWillReceiveProps باستخدام هذا السطر في المستندات:

لا يتم استدعاء componentWillReceiveProps () إذا قمت فقط باستدعاء this.setState ()

لكن التحذير من استخدام componentWillReceiveProps هو أنني سأضطر إلى تمرير nextProps إلى الوظائف.

سأحاول اتباع نصيحتك. شكرا أقدر ذلك.

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

ماذا لو استخدمنا هذا جنبًا إلى جنب مع shouldComponentUpdate؟
حيث لا نرغب في تحديث حالة المكون أو إعادة العرض ،
لكننا نحتاج إلى this.props لاستخدام أحدث الدعائم للقيام ببعض أعمال البرنامج النصي اليدوي بعد استلام الدعائم

عملي هو ضبط this.props على الدعائم الجديدة قبل تشغيل الوظيفة المطلوبة

سيكون من الجيد حقًا أن يكون لديك ComponentDidMount أو بعض الخطاف لذلك. لماذا ا؟ لأنه ، في بعض الأحيان ، نحتاج إلى إجراء حسابات أخرى لا تعتمد على دورة حياة React.

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

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