React: كيفية تنفيذ shouldComponentUpdate مع this.context؟

تم إنشاؤها على ١٣ نوفمبر ٢٠١٤  ·  126تعليقات  ·  مصدر: facebook/react

أعلم أن this.context ليس هناك رسميًا ولكن عدد قليل من المكتبات يعتمد عليه ، ويبدو أنه يتشكل مع # 2509.

أنا أحاول أن أفهم كيف بالضبط shouldComponentUpdate من المفترض أن يتم تنفيذها مع context في الاعتبار. لقد لاحظت أنها تقبل وسيطة ثالثة ( nextContext ) ويمكنني تمديد PureRenderMixin للتحقق منها أيضًا:

  shouldComponentUpdate: function(nextProps, nextState, nextContext) {
    return !shallowEqual(this.props, nextProps) ||
           !shallowEqual(this.state, nextState) ||
           !shallowEqual(this.context, nextContext); // this will throw without context, read on
  }

المكونات التي لا تشترك في this.context خلال عدم حذف contextTypes لن تحصل على هذه الوسيطة الثالثة ، وهو أمر مفهوم.

ومع ذلك ، فإن هذا يمثل مشكلة عندما يكون لدينا مكون <Middle /> بين <Top /> مالك السياق و <Bottom /> مستهلك السياق. إذا قام <Middle /> بتنفيذ shouldComponentUpdate مقيدًا ، فلا توجد طريقة لـ <Bottom /> للتفاعل مع تحديثات سياق <Top /> على الإطلاق:

( كمان )

var Bottom = React.createClass({
  contextTypes: {
    number: React.PropTypes.number.isRequired
  },

  render: function () {
    return <h1>{this.context.number}</h1>
  }
});

var Middle = React.createClass({
  shouldComponentUpdate: function (nextProps, nextState, nextContext) {
    return false;
  },

  render: function () {
    return <Bottom />;
  }
});

var Top = React.createClass({
  childContextTypes: {
    number: React.PropTypes.number.isRequired
  },

  getInitialState: function () {
    return { number: 0 };
  },

  getChildContext: function () {
    return { number: this.state.number };
  },

  componentDidMount: function () {
    setInterval(function () {
      this.setState({
        number: this.state.number + 1
      });
    }.bind(this), 1000);
  },

  render: function() {
    return <Middle />;    
  }
});

React.render(<Top />, document.body);

قد تحدث نفس المشكلة إذا حاولت إعطاء Middle اسمًا عامًا على علم بالسياق shouldComponentUpdate كما كتبت أعلاه ، لأن Middle ليس لديه this.context إلا إذا اختار في.

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

هل سيحل هذا بواسطة # 2112؟ هل هناك حل آخر في هذه الأثناء؟ ما هي الطريقة الموصى بها؟

Component API Bug

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

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

بشكل أساسي ، عندما يتغير سياق الوالدين ، يجب أن يحدد جميع أحفاده الذين يتلقون هذا السياق على أنهم متسخون ، بغض النظر عن بعدهم. يجب أن يكون لتغيير سياق الأسلاف نفس تأثير تغيير الحالة للأحفاد الذين اختاروا هذا السياق - يجب أن يتلقوا context جديدًا بغض النظر عما قاله آباؤهم.

ال 126 كومينتر

هذا سؤال جيد للغاية. شكرا لرفعها!

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

sebmarkbage - الأفكار؟

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

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

بشكل أساسي ، عندما يتغير سياق الوالدين ، يجب أن يحدد جميع أحفاده الذين يتلقون هذا السياق على أنهم متسخون ، بغض النظر عن بعدهم. يجب أن يكون لتغيير سياق الأسلاف نفس تأثير تغيير الحالة للأحفاد الذين اختاروا هذا السياق - يجب أن يتلقوا context جديدًا بغض النظر عما قاله آباؤهم.

gaearon أعتقد أنك في هذه الحالة تحتاج إلى إعادة shouldComponentUpdate تأثير في تقليم الأشجار الفرعية. وإلا فسيكون السياق في حالة غير متناسقة مع شجرة العناصر.

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

أعتقد أن shouldComponentUpdate على المكونات الوسطى لا يجب أن يكون له أي تأثير على ما إذا كان أحفادهم يتلقون السياق الجديد ، تمامًا مثلما لا يؤثر على ما إذا كانوا يتلقون الحالة الجديدة:

http://jsbin.com/geseduneso/2/edit؟js ، الإخراج

(إذا كان هذا هو الحال ، فسيتم زيادة الرقمين)

أين التناقض؟

لوضعها بشكل مختلف ، أعتقد أن context يجب أن يعمل تمامًا كما لو كان مالك السياق لديه شيء مثل "متجر" يتم فيه كتابة نتيجة getChildContext() في componentWillUpdate ، وجميع مستهلكي السياق التابع الذين أعلنوا مفاتيح من هذا السياق في contextTypes ، يجب أن يتلقوا هذا السياق كما لو كانوا مشتركين في هذا "المتجر" وقاموا بتحديث حالتهم الخاصة.

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

تحرير: هذا لن يعمل لأن الوالدين قد يتغيرون

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

ولكن بعد ذلك ، فإن الحل المعقول الوحيد الذي أراه هو منع تغييرات السياق تمامًا. أي ، اجعل getChildContext() مشابهًا لـ getInitialState() ، والذي يتم استدعاؤه مرة واحدة فقط قبل تثبيت المكون.

هذا من شأنه أن يجعل السياق أسهل بكثير للتفكير فيه. يمكننا إزالة المعلمة الثالثة من shouldComponentUpdate لأن السياق لا يتم تحديثه أبدًا.

في حال كنت بحاجة إلى تحديثات من مالك السياق (على سبيل المثال ، يريد جهاز التوجيه التفاعلي تمرير activeRoutes من أعلى إلى أسفل للاستخدام في ActiveState mixin ccmjackson) ، لا شيء يمنعك من تجاوز { addChangeListener, removeChangeListener, getActiveRoutes } context . يمكن الآن للأحفاد الاشتراك في التغييرات ووضعها في state .

هل هذا حل معقول؟

أعتقد أن السؤال الرئيسي الذي يجب الإجابة عليه هو:

في أي سيناريوهات يتم تمرير _data_ عبر context مفضلًا لتمرير البيانات عبر props أو تشغيل حدث لاستدعاء المكون setState .

لقد كنت أستخدم السياق لتمرير مراجع الكائنات حولها بسعادة تامة ، حيث إنني أكتب فقط لتلك الكائنات ، وليس للقراءة. على سبيل المثال this.context.triggerAction("something")

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

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

أعتقد أنه يمكننا إيجاد حل يتجنب جعل المستخدمين يربطون مستمعي التغيير.

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

سأتحدث مع

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

أوتش. أنت محق تمامًا ، لم أفكر في هذا.

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

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

لقد تجاذبت أطراف الحديث مع sebmarkbage ،

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

sebmarkbage ، اسمحوا لي أن أعرف إذا فاتني أي شيء!

على الرغم من المناقشات الجيدة! شكرا لكل الردود!

شكرا لأخذ الوقت لمناقشة هذا!

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

إذا قام أحد مكونات المستوى الأعلى Feed بتنفيذ shouldComponentUpdate باستخدام PureRenderMixin لتجنب التحديثات الإضافية ، فهذا لا يعني أن Feed يعرف أنه في مكان ما بداخله هو Cell والذي يحدث أنه يحتوي على Link الذي يعتمد على سياق جهاز التوجيه.

يزداد الأمر سوءًا عندما تستخدم الأطر (مثل إطار عمل توجيه React الأكثر شيوعًا ) السياق وقد لا تكون على دراية به. في مكان ما ، هناك تطبيقات لا تغير حالة الارتباط النشط لأن شخصًا ما قام بتحسين مكونات المستوى الأعلى ولديه حرفياً _ لا فكرة _ كان عليه أن يعلن ما يقابل contextTypes إلى _ even get_ nextContext في shouldComponentUpdate .

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

بعض الأطر الموجودة أعلى React ، مثل PureRenderMixin -ish shouldComponentUpdate _default_ ، من الغريب قطعها بهذه الطريقة. هذا يعني كسر السياق shouldComponentUpdate في كل مكون لهم.

أوافق على أن هذا لا يحظر عملك ، لكن لا يمكنني الموافقة على أن الوضع الحالي مرضٍ إذا كان سيتم استخدام السياق على الإطلاق. ليس من الصعب فقط تنفيذ shouldComponentUpdate مع السياق الآن - إنه مستحيل تمامًا ما لم نفترض أن كل مكون يدرك دائمًا ما يمكن أن يكون children .

تعتمد المكتبات الشعبية بالفعل على السياق بشكل كبير. أتفهم أنها ليست ميزة مدعومة ، ولكن في رأيي يجب أن تكون على الأقل _ ممكنة_ لجعلها تعمل مع shouldComponentUpdate ، أو يجب تعطيلها ، ويجب إجبار المكتبات على عدم استخدامها ، لأنها مكسور بمهارة.

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

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

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

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

صحيح ، كان دائمًا نوعًا ما عديم الفائدة.

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

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

لكنه يطرح السؤال: كيف نعرف متى يتغير السياق؟ بالنسبة إلى الحالة والدعائم ، لدينا setState و render / setProps . يبدو أننا سنحتاج إلى الاحتفاظ بنسخة من السياق الحالي في مكان ما ونفرقه مع النتيجة من getChildContext عندما يتم استدعاء render .

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

لذا ، بالنظر إلى مثال ،

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

var peopleStore = this.context.peopleStore;
var person = peopleStore.get(this.props.personId);
return <div>person.fullName</div>;

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

في هذا المثال ، إذا كان "الأشخاص" هم "مستخدمي fb" ، فهو متجر غير متزامن كبير ومعقد. هل يجب علي إعادة استخدام هيكل المتجر لـ PersonStore؟ واحد للمجموعة العامة (getFriends ، getPerson ، إلخ) ولكن العديد من الأمثلة الفريدة لنوع متجر الأشخاص لشخص فردي.

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

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

أتوقع أن يقوم منطق التطبيق أولاً بإزالة / تدمير متجر People الحالي. لذلك ، يحتاج المكون الخاص بي إلى التوقف عن الاستماع إلى التحديثات. لهذا ، أوصي بـ ReactClass API. على سبيل المثال ،

onContextChange (سابق ، جديد)

يمكن للعنصر حينئذٍ مقارنة مثيلات peopleStore. دعنا نتجاهل البيانات العامة ونفترض أن PeopleStore الجديد فارغ. سيقوم العنصر بإلغاء الاشتراك من المتجر السابق وتشغيل العرض (). سيُظهر العرض بعد ذلك بعض رسائل النوع "مستخدم غير معروف".

عندما يقوم المستخدم بتسجيل الدخول كمستخدم آخر ، يتم إنشاء متجر جديد ، ويعاد توصيل العنصر ، ويقوم العرض () بعمله مع البيانات الجديدة.

وراء الكواليس ، لا يمكن أن يكون "this.render ()" متزامنًا. لكي يكون أي من تصميمي / مثالي منطقيًا على الإطلاق ، يجب جمع استدعاءات العرض () بواسطة إطار العمل وتجميعها معًا.

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

هناك قدر كبير من الاهتمام بهذا. (انظر المراجع أعلاه.)

نعم gaearon .

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

أنظر أيضا
https://github.com/yahoo/react-intl/issues/58
https://github.com/facebook/react/issues/3038

slorber لقد تبنت أيضًا PureRenderMixin مخصصًا ، فمن الواضح أنه يمكن كسره باستخدام shouldComponentUpdate s الأكثر صرامة في المنتصف ، كما يقول gaearon (أو إذا اختفت المعلمة الثالثة) ومع ذلك ، يمكنك دائمًا الاعتماد على الدعائم. دعونا نرى كيف ستتطور هذه المشكلة :)

gpbl تحقق مما يلي:
https://github.com/facebook/react/issues/3038#issuecomment -76449195

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

slorber Calling unmountComponentAtNode يجعل تجربة المستخدم سيئة ، لأنه يتسبب في خسارة كل الولايات المحلية.

أعتقد أن الوقت قد حان لإعلان السياق ميزة رسمية. لا يعد استخدام السياق خيارًا لمعظم الأشخاص ، لأن جهاز التوجيه و ReactIntl ​​يستخدمه.

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

cody ، هذه ليست مشكلة في فقدان الحالة المحلية بالنسبة لي ، لأنني لا أملك أي ولاية محلية ويدير تطبيقي بالكامل الحالة الثابتة خارج React تمامًا :) تحقق من الفيديو الذي قمت به للإطار: https: / /github.com/stample/atom-react

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

نعم ، shouldUpdateChildContext يجعلها جميلة ومتناسقة.

أي فرصة لهذا للذهاب إلى 0.14؟

إذا قمت بتصميم واجهة برمجة تطبيقات لطيفة وتنفيذها. :)

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

من غير المحتمل أن يكون لدى فريقنا الأساسي بدوام كامل الوقت وحده لذلك. :(

في 9 أبريل 2015 ، الساعة 1:32 مساءً ، كتب Dan Abramov [email protected] :

أي فرصة لهذا للذهاب إلى 0.14؟

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub.

بالتأكيد ، سألقي نظرة!

آسف يا رفاق ، ما زلت لا أجد الوقت لبدء العمل على هذا. بعد إصدار React DnD 1.0 المعلق ، سأكون مشغولاً بالتحضير لـ conf ، لذلك من غير المحتمل أن أتمكن من العمل على هذا في أي وقت قريبًا. :-(

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

الشيء الوحيد الذي كنت أتساءل عنه هو ما إذا كانت العبارة التالية صحيحة أم لا:

يجب أن يكون السياق الفرعي للمكون _ دائمًا_ تقليلًا لدعائم الحالة الخاصة به والسياق

هذا يضمن أنه يمكننا تدفق البيانات بشكل موثوق به خلال دورة الحياة المعروفة. هذا مشابه لبيان أن "تصيير المكوّن هو دائمًا اختزال للحالة والدعامات".

هذه هي الطريقة التي أتخيلها حاليًا - سيكون من الجيد معرفة ما إذا كنت خارج المسار تمامًا!:

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

يبقى shouldComponentUpdate مع 3 معامِلات ، لذا يمكن لمكوِّن في الشجرة الفرعية المذكورة أعلاه أن يقرر ما إذا كان يجب عليه تحديث أي شيء بالفعل (ملاحظة: إرجاع القيمة false هنا لا يؤثر على السياق المتدفق إلى أسفل الشجرة الفرعية بشكل أكبر)

شيء آخر أتساءل عنه هنا هو ما إذا كان يجب أن يكون هناك طريقة أخرى جديدة لدورة الحياة componentWillReceiveContext ؟ - تم استدعاؤه في وقت مشابه لـ componentWillReceiveProps لكن ضمن تدفق بيانات السياق. من الممكن هنا استدعاء هاتين الطريقتين في "نفس الوقت".

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

يرجى القفز عليها! أنا مشغول جدًا بأشياء أخرى في الوقت الحالي.

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

كما نضع في اعتبارنا هناك observe هوك أن القوة أو قد لا تحصل على تنفيذها في 0.14. مما يعني أنه قد يكون هناك أو لا يتم اشتقاق data / observed / أيا كان اسمه. لكن من المحتمل ألا يكون ذا صلة بمهمتك في الوقت الحالي.

حصلت على مسودة أولية جدًا من هذا على مفترقتي ويمكنك رؤيتها تعمل عند examples/context/index.html

لقد ذهبت مع إنشاء علاقة بسيطة "أصل السياق" / "سياق الطفل". "أصل السياق" هو ​​أي مكون قد يغير سياقه الفرعي (على سبيل المثال ، ينفذ childContextTypes ) و "سياق تابع" هو أي مكون يعتمد على السياق أو قد يغير سياقه الفرعي (على سبيل المثال ، يقوم بتنفيذ contextTypes أو childContextTypes ). يتم إعداد هذه العلاقة عندما يتم تثبيت المكونات حاليًا.

عند بدء تشغيل دورة حياة تحديث المكون ، لدينا حالتان:

  1. إذا كان المكوّن يقول أنه لا يتم تحديثه (على سبيل المثال ، shouldComponentUpdate() === false ) فإننا نتحقق مما إذا كان يجب علينا تحديث السياق الفرعي بـ shouldUpdateChildContext . إذا كان هذا هو true (افتراضي) ، إذا كان هذا المكون يحتوي على أي "سياق توابع" فوري ، فإننا ننقل المكون الفرعي إلى دورة حياة التحديث. يستمر هذا حتى نصل إلى نهاية شجرة السياق أو نصادف shouldUpdateChildContext() === false
  2. إذا قال أحد المكونات إنه يتم التحديث ، فلا شيء مختلف. لا يوجد توجيه جانبي لبيانات السياق في هذه الحالة ونترك التدفق الطبيعي يستمر حتى يصل المكون إلى الحالة رقم 1 مرة أخرى.

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

للحصول على مثال psuedo سريع ، ضع في اعتبارك ما يلي:

<Root num={1}>  // Gives context {num: this.props.num}
  <Mid>         // Ignores any context and shouldComponentUpdate() === false
    <Child>     // Requires context {num: propTypes.number}

بالنسبة للتصيير الأولي (التثبيت) ، كل شيء كما نتوقع. (التفاصيل الضمنية: يتم إنشاء علاقة الوالدين / الطفل بين Root و Child )

قمنا بتحديث Root لتصبح قيمة الخاصية num 2

<Root num={2} />

ينفذ Mid أيضًا طريقة shouldComponentUpdate() والتي تُرجع false لأنها render() الطريقة لا تهتم بـ context.num ولم يتغير شيء آخر - فلماذا يجب تحديثه؟

هذا هو المكان الذي في الحالات القديمة لن يرى المكوِّن Child السياق الجديد أبدًا لأننا أخرجنا التحديث من الشجرة.

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

إذا كان shouldUpdateChildContext() هو true (افتراضيًا) ، فإننا نقوم بتحديث كل من أقرب "سياق الأطفال" (فقط Child في حالة المثال) إذا تم إعداد أي علاقات مسبقًا . سيؤدي هذا إلى وضع هذا المكون في دورة حياة التحديث الخاصة به (على عكس المناقشات التي رأيتها سابقًا ، سيستمر هذا الأمر في استدعاء shouldComponentUpdate() كالمعتاد مع السياق _new_ باعتباره المعلمة الثالثة حيث أن هذا يوفر للمكون تحكمًا دقيقًا عندما يريد ذلك تحديث).

نأمل أن يشرح ذلك العملية بشكل جيد بما فيه الكفاية!

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

  • تحقق من تحديثات الطفل حتى إذا قام الأصل shouldComponentUpdate() بإرجاع خطأ.
  • تحقق من تحديثات الطفل حتى إذا قام الأصل shouldUpdateChildContext() بإرجاع خطأ.
  • تحقق من أن الطفل لا يقوم بالتحديث إذا قام المكون shouldUpdateChildContext() بإرجاع خطأ.

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

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

cc: sebmarkbage للحصول على تعليقات حول تصميم / فكرة API.

Chrisui هذا يبدو رائعًا حتى الآن ، شكرًا لك على القيام بهذا العمل.

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

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

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

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

سأحصل على اختراق سريع وأحاول السخرية من هذا الآن!

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

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

في الواقع ، بدأ هذا التطبيق في الظهور وكأنه نظام اشتراك. نظرًا لأن context هو نطاق عالمي فعليًا ، فربما يكون الحل الصحيح هو مطالبة المكونات بالاشتراك الجانبي في متغيرات السياق ، مما يسمح لنا باستخدام نفس الآلية للسياق الذي سنستخدمه لجميع الاشتراكات الأخرى إلى العالمية البيانات. راجع https://github.com/facebook/react/issues/3398 و https://github.com/facebook/react/issues/3858 و https://github.com/facebook/react/pull/3920 للحصول على معلومات ذات صلة.

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

jimfb أنت محق في إعادة عرض مئات المكونات ولكني لست متأكدًا من أن الأمر مختلف عما هو عليه الآن إذا قمت بإجراء بعض التغييرات في الحالة وكان عليك تنفيذ shouldComponentUpdate لمنع حدوث تحديث جماعي.

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

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

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

نعم ، أشعر بالفضول لمعرفة ما يفكر فيه الآخرون بشأن استخدام حل تحميل البيانات الجانبي.

أعتقد أن السياق متعامد في الغالب لتحميل البيانات بشكل جانبي

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

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

في 26 مايو 2015 ، الساعة 22:10 ، كتب Jim [email protected] :

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

نعم ، أشعر بالفضول لمعرفة ما يفكر فيه الآخرون بشأن استخدام حل تحميل البيانات الجانبي.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub.

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

class Mid extends Component {
  shouldComponentUpdate() { return false; }
  shouldUpdateChildContext() { return false; }
  ...
}

أنا سعيد بالبساطة النسبية للسياق كما هو + shouldUpdateChildContext. نأمل ألا يؤدي تغيير الآلية الأساسية لتتماشى مع الاشتراكات العالمية الأخرى إلى تقليل سهولة استخدامها بشكل كبير.

تضمين التغريدة
كماeplawless وأشار إلى shouldUpdateChildContext يمكن استخدامها لمنع فروع ضخمة من شجرة الخاص بك يتم تحديثه.

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

اقتراح آخر: يمكننا أيضًا جعل shouldUpdateChildContext () افتراضيًا على خطأ لمنع هذا السلوك الجديد افتراضيًا وجعله مشتركًا.

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

فتحت لك العلاقات العامة: https://github.com/facebook/react/pull/3973

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

أنت تعلم أنني أعتقد أنني كنت مخطئًا في الأصل بشأن shouldUpdateChildContext . هل حقا نحن بحاجة له؟ آسف على الضرب.

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

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

سأفكر في الأمر أكثر وأعلق على العلاقات العامة مع التفاصيل ...

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

أعتقد أن المشكلة الأكبر ، كما أشار mjackson ، هي أننا لا نعرف متى تغير متغير السياق. هل نريد حقًا إعادة تصيير كل عقدة نصية fbt / i18n في كل مرة يحدث فيها إعادة تصيير i18n ContextProvider؟ لم نقدم طريقة للقول "لا تقلق ، لم يتغير شيء ، لا تهتم بإعادة عرض كل عنصر نصي على الصفحة".

أنا مرتبك قليلاً بشأن فقرتك الأخيرة ؛ هل يمكنك التفصيل؟ أفترض أنك لا تقترح أن ما يلي هو مضاد لنمط السياق: يقوم مكون i18n "ببث" إلى جميع المكونات التابعة لـ i18n ، وهي اللغة المفضلة للمستخدم / المنطقة الزمنية / التنسيق / إلخ.

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

sebmarkbageChrisuijimfb

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

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

في الوقت الحالي ، نستخدم مزيجًا من حين لآخر للتركيز ومجموعات الصوت من نفس المصدر. أعتقد أن هناك حالات استخدام صالحة لعدم فرض تعيين 1: 1 ، على الرغم من أنني أفهم الرغبة في التقييد.

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

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

<Table>
  <Cell />
  <Cell />
  <FancyCell />
</Table>
class FancyCell {
  render() {
    return <SomeWhatFancyCell>Some content</SomeWhatFancyCell>;
  }
}

class SomeWhatFancyCell {
  render() {
    return <Cell>{this.props.children}</Cell>;
  }
}

خذ borderWidth وقم بتمريره إلى جميع خلايا الجدول بالصيغة borderLeft/Top/Right/Bottom .

إحدى الطرق الرائعة هي تمرير borderWidth إلى <Table /> ، وتقسيمه وتمرير السياق.

إنه يوفر طريقة لشيء قد يتم عرضه لخلية للتواصل مع أصلها المفاهيمي مثل الجدول من خلال قناة مخفية. هذا بالفعل ما تفعله عناصر DOM مع بعضها البعض ومن المحتمل أن تكون مطلوبة لعمل التخطيط في React.

لا تفرط في التركيز على مفهوم "السياق". المفهوم الحالي ليس مثاليًا. ربما يكون المثل الأعلى شيئًا مثل مفهومين مختلفين أو قناة أخرى؟

واجهة برمجة تطبيقات بديلة معقولة:

class Table {
  render() {
    var w = this.props.borderWidth;
    var borderStyle = { left: w, right: w, top: w, bottom: w };
    return <context key={someSymbol} value={borderStyle}>{this.props.children}</context>
  }
}
class Cell {
  static contextKey = someSymbol;
  render() {
    var borderStyle = this.context;
    ...
  }
}

مجرد البصق هنا.

استمرار البصاق ...

يمكن استخدام بناء جملة بديل ...

<Table borderStyleChannelKey="myKey">
  <Cell borderStyle={myKey} />
  <Cell borderStyle={myKey} />
  <FancyCell borderStyle={myKey} />
</Table>

لقد جعلت الآن قناة الاتصال واضحة ، وتجنب كل احتمالات تعارض الأسماء ، وما إلى ذلك (https://github.com/reactjs/react-future/pull/28)

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

راجع للشغل ، جوهر React هو بالفعل قناة اتصال مخفية: الحالة. لا يمر صراحة من خلال كل طفل.

أطلق عليه اسم "styleinfo" أو "celldata" بدلاً من "borderStyle" ، واجعله كائنًا. ثم لا تتطلب إضافة الحقول / المعلومات تغيير عقد واجهة برمجة التطبيقات بين Table و Cell .

الاختلاف الوحيد بين المتغير الخاص بي والمتغير الخاص بك هو أن الطريقة الوحيدة (في المتغير الخاص بي) هي الطريقة الوحيدة للطفل "لقراءة" القيمة فعليًا هو تمريرها صراحة كدعم من الوالدين. من الناحية الوظيفية ، فإن اقتراحك الأخير مطابق حرفياً لاقتراحي من https://github.com/reactjs/react-future/pull/28.

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

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

أعني رمزًا عالميًا (رأس المال S) يجب تنسيقه من خلال بعض القنوات مثل وحدة نمطية مشتركة. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol

الجزء اللطيف حول واجهة برمجة التطبيقات الجديدة المقترحة هو أن المفتاح ليس مفتاح "خاصية الكائن" والذي يتم الخلط بينه وبين التحكم في التدفق وتحليل البرنامج. في اقتراحي قيمة ديناميكية من الدرجة الأولى تمامًا مثل المفتاح الذي يُمكّن الدولة.

أوه ، ic ، sebmarkbage يقوم بسحب جافا سكريبت جديد

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

أتمنى لو كنت في المكتب اليوم! أشعر أن هذا سيكون محادثة رائعة بشكل خيالي أن أجريها شخصيًا!

أنا شخصياً سعيد لأنه لم يكن كذلك ، لأن هذا يبقينا جميعًا في الحلقة أيضًا ؛-).

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

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

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

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

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

لست متأكدًا تمامًا من تشبيه "الثقب الدودي" ، وسيناريو البث ومثال i18n هي تلك التي واجهت فيها المشكلة التي تهدف العلاقات العامة المقترحة إلى حلها.

لست واضحًا تمامًا أيضًا كيف يساعد https://github.com/facebook/react/issues/2517#issuecomment -106597895 - يبدو هذا مكافئًا لغويًا لـ getChildContext و ContextTypes بالنسبة لي.

ما أحبه في shouldUpdateChildContext PR هو أنه لا يتطلب تعداد جميع الأطفال في أي عمق لنشر تغييرات السياق.

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

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

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

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

من الواضح أن السياق يحتاج إلى أن يكون "محميًا" إلى حد ما من المكونات التي لا علاقة لها بالسياق المعين - لكن يجب أن يكون من السهل القفز إلى تدفق البيانات إذا أراد أحد المكونات ذلك. في الحالة المحددة لمكونات النموذج الخاصة بنا ، يجب عزل معظم العناصر الفرعية لـ Form عن السياق الذي يمر به ، ويجب أن يستلمها فقط المكون Field . ومع ذلك ، إذا أراد المستهلك أن يلف Field في HoC (لتعيين الإعدادات الافتراضية أو ضبط السلوك) ، فيجب أن يكون هناك طريقة مباشرة للقيام بذلك.

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

لقد لعبت قليلاً مع فكرة السياق القائم على الاشتراك في سياق رد الفعل .

تحت الغطاء ، يعرض مذيعو السياق واجهة { subscribe(key, cb), getValue(key) } لأطفالهم. يؤدي الاشتراك في مفتاح السياق إلى ظهور فقاعات في شجرة السياق حتى تصل إما إلى مذيع لهذا المفتاح المعين أو إلى قمة الشجرة. يرسل المذيعون التغييرات إلى مفاتيح السياق عبر broadcast({ [key]: newValue, ...otherKeys }) .

@broadcasts([...keys]) و @observes([...keys]) يربط مصممو فئة API هذه بمكونات React ، باستخدام context لنشر شجرة السياق من خلال شجرة المكون و setState لإدراج تحديث في قائمة استجابة لتغيير السياق.

باستخدام القليل من النموذج المعياري ، يمكنك إعداد API يعادل عرض shouldUpdateChildContext .

لتجنب تضارب الأسماء ، تكون أشجار السياق

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

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

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

لإضافة 2 سنت هنا ، أفضل بشدة ما إذا تم تنفيذ أي إصلاح هنا بطريقة لا تؤدي إلى كسر StaticContainer .

أعتقد أنه سيكون من المنطقي أن يستمر StaticContainer في العمل كما فعل ، وحظر جميع التحديثات القادمة من الوالدين ، كلاهما props و context .

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

@ jedwards1211 ستكون حالة الاستخدام الخاصة بي هي إحضار رسائل الترجمة داخل مكون I18nProvider ثم تمرير مثيل Jed (باستخدام طرق gettext).

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

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

التخلص من هذا باستخدام jquense قليلاً على Reactiflux ؛ سيكون مفيدًا إذا كان هناك مفهوم "super false " لـ shouldComponentUpdate .

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

على سبيل المثال ، ضع في اعتبارك https://github.com/rackt/react-router/pull/2454 - بدون القدرة على حظر تحديثات السياق للأطفال ، لن نتمكن بسهولة من منع التحديثات لربط الحالة النشطة عند النقل- مكون الطريق.

أنا أوافق على أن سلوك shouldComponentUpdate يعيد false يجب ألا يحظر تحديثات السياق ، ولكن يجب أن يكون هناك نوع من SUPER_FALSE حارس للاحتفاظ <StaticContainer> العمل كما هو.

taion

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

أنا محتار ، ما هي حالة الاستخدام المطلوبة؟ بشكل عام ، لا يجب استخدام shouldComponentUpdate لحظر التحديثات التي قد تؤدي إلى تغييرات في واجهة المستخدم. إنه تلميح مقصود به أن يكون آلية تحسين للسماح لك بتجنب القيام بأعمال المصالحة غير الضرورية.

jimfb أنت بالفعل تستخدم <StaticContainer> للقيام بذلك بالضبط في Relay ، على الرغم من ذلك - أي حظر التحديثات أثناء تحميل بيانات جديدة.

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

يبدو أن هذا يتم تحقيقه حاليًا من خلال إرجاع false دائمًا في shouldComponentUpdate أثناء تحميل حالة جهاز التوجيه الجديد.

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

ccsebmarkbage

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

ربما يكون من الأسهل عليك القيام بذلك (:

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

من خلال إرجاع false من shouldComponentUpdate ، فإن حاوية الجذر / جهاز العرض Relay لديها طريقة سهلة لمجرد الحفاظ على عرض ما كان موجودًا من قبل.

إنه لا يمنع التفاعلات في حد ذاته - إنه يمنع البيانات الأولية التي تجلب التحديثات أثناء وجودها في حالة عابرة.

taion نعم ، أفهم ما يفعله ، لكني

عادةً ما تكون الطريقة التي تنجز بها هذا السلوك هي وضع القيم القديمة في الحالة (حتى تظهر / تصل القيم الجديدة) وتجسيد القيم القديمة من الحالة.

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

هذا النمط ممكن فقط مع البيانات غير القابلة للتغيير أو شيء مشابه. إذا كان لديك كائنات ذات حالة (غير قابلة للنسخ) ، فقد لا تتمكن من اتباع هذا النمط. أظن أن Relay قد لا تواجه هذه المشكلة ، لكن التطبيق الحالي لـ React Router يعاني من هذه المشكلة.

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

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

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

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

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

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

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

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

يمكنني التعامل مع ذلك - أعتقد أننا قمنا بتنظيف بعض الأشياء على جانب React Router بحيث يمكننا الابتعاد عن استخدام هذا النمط على أي حال.

شكر!

أريد أيضًا إضافة سؤال آخر. لدي شيء من هذا القبيل.

var BlogPosts = React.createClass({
  getChildContext: function() {
    return {
      currentBlogPost: this.props.currentBlogPost,
      currentUser: this.props.currentUser
    };
  },

  childContextTypes: {
    currentBlogPost: React.PropTypes.object,
    currentUser: React.PropTypes.object
  },

  render: function() {
    return <BlogPosts blogPosts={this.props.blogPosts}/>
  }
});

function select(state) {
  const { blogPosts, currentUser, currentBlogId } = state;
  console.log( state.blogs[currentBlogId]); 
  // first time the above is undefined and then blogs get populated and I have the object;
  return { blogPosts, currentUser, currentBlogPost: state.blogs[currentBlogId] };
};

export default connect(select)(BlogPosts);

يوجد الآن في مكون BlogPosts BlogPostText أو BlogPostImage أو PodCast ... اعتمادًا على ما إذا كان نوع blogPosts [index]. هو نص أو صورة أو صوت.

في أحد المكونات التي قمت بفحصها للمالك مثل هذا ،

var BlogPostText = React.createClass({
  canDeleteMemory: function(post, blog, user) {
    return user && (blog.userId == user.id || post.userId == user.id)
  },
  render: function() {
    let isOwner = this.canDeleteMemory(this.context.currentBlogPost, post, this.context.currentUser);
    return isOwner ? <a>Delete</a> : null;
  }
});

ثم أحصل دائمًا على خطأ في blog.userId لأن المدونة غير محددة ... لذلك قمت بتغيير الحالة مثل هذا let isOwner = this.context.currentBlogPost && this.canDeleteMemory(this.context.currentBlogPost, post, this.context.currentUser);
ولكن بعد ذلك ، لا تظهر أيقونة الحذف أبدًا ... ولكن بدلاً من استخدام ContextType إذا قمت بلف مكون BlogPostText مع redux ، حدد واستخدم this.props.currentBlogPost ثم يعمل بشكل جيد ..

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

@ aghosh47 أعتقد أن تغيير السياق يؤدي إلى إعادة عرض ، لكن من الممكن أن نكون قد فوتنا حالة الحافة. إذا كان بإمكانك إنشاء jsfiddle بسيط يوضح المشكلة ، فسيساعدنا ذلك في التحقيق.

يرجى أيضًا نشره في إصدار جديد ، حيث نريد إبقاء مشكلات github في الموضوع ، إلى أقصى حد ممكن.

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

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

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

@ jedwards1211 بصراحة ، لا أتذكر أين تمت مناقشتها. من المحتمل تمامًا أنه كان نقاشًا شخصيًا ، ولكن هناك العديد من المناقشات التعويضية عبر الإنترنت وربما تجدها هناك.

بينغ @ aghosh47

ها ها ها ها

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

لذلك ، إذا تغيرت الدعائم في الوالد ، سينعكس السياق في الأطفال ... شكرًا.

ما الخطأ حقًا في استخدام النافذة لكائن واحد يخزن تلك الكرة الأرضية؟

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

في ملاحظة جانبية ، هذا السؤال ليس له أي علاقة بالمشكلة ، أليس كذلك؟ :غمزة:

fatfisz لا أعرف جيدًا حالات الاستخدام الخاصة بك ، يمكنك أيضًا الحصول على ('foo') يشير إلى خاصية نافذة على العميل فقط

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

شكر

ما الخطأ الذي تفعله:

// context.js
module.exports  = { // sorry for using commonjs, since most of you use import/export I guess
  // some shared variables, initialized and used by components
};

ثم يتطلب ('./ Context.js') ؛ في جميع الملفات التي تحتاج إلى الوصول إلى متغيرات السياق والطرق

ربما لا يتم احترام التغليف ، ولكن حسنًا ..

(gaeron)

سياق cauburtin مفيد لأن:

1) يمكن أن تتغير وتحفز إعادة العرض على عكس صادرات الوحدة
2) يمكن للوالد تجاوزها ، وهي أكثر ميزة مفيدة لها
3) لا يجب أن يكون منفردًا ، وهو أمر مفيد لتقديم الخادم حيث تريد عزل البيانات

متفق عليه 2) و 3)
ل 1) لم أحتاج إلى القيام بذلك حتى الآن ، ولكن يمكنك تمرير مثيل رد الفعل في السياق أيضًا (لقد سمعت غالبًا أنها ممارسة سيئة ، ربما تعتقد ذلك أيضًا ، ولكن تم ذكر ذلك في المستندات: تذكر ذلك يمكنك أيضًا تمرير مكونات React بالكامل في props إذا كنت ترغب في ذلك (حيث يمكن أن تكون props هذا السياق الفردي بدلاً من ذلك في هذه الحالة). بالنسبة لي ، فإن React هي العرض ومستمعي الأحداث وجهاز التحكم عن بعد (العلوي / الجذر). سيكون هذا السياق المشترك بمثابة وصول مشترك إلى جهاز التحكم عن بُعد. يمكن تحديث المكونات الفرعية عند تغيير أدواتها ، وربما الوصول إلى هذا السياق العالمي واستخدامه. (لست من محبي الفردي في هذه الحالة على وجه الخصوص ، يمكنني إعادة استخدام رد فعل المثيل بطريقة الدعائم ، إذا كان ذلك مفيدًا ، يمكن أن يكون هذا `` التمرير '' آليًا / مخفيًا إلى حد ما بواسطة فئة أو تكوين رئيسي مشترك)

حسنًا عند كتابة هذا ، أدرك أن فكرة السياق الفردي سيئة :)

الأمر المربك هو أن مستندات React لا تدعو كثيرًا لاستخدام السياق ، فهي مثل الدعائم الاختيارية في الواقع ، حيث تحصل عليها عندما تطلبها؟

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

'use strict';

    var React = require('react-native');
    var { View,
          StyleSheet,
          TouchableHighlight,
          } = React;

    var DrawerLayout = require('react-native-drawer-layout');
    var DrawerScreen = require('./DrawerScreen');
    var DrawerMenu = require('./DrawerMenu');

    var DrawerLayoutExample = React.createClass({

      render: function() {
        var navigationView = (
          <View >
               <DrawerMenu/>
          </View>
        );

        return (
          <DrawerLayout
            onDrawerSlide={(e) => this.setState({drawerSlideOutput: JSON.stringify(e.nativeEvent)})}
            onDrawerStateChanged={(e) => this.setState({drawerStateChangedOutput: JSON.stringify(e)})}
            drawerWidth={200}
            ref={(drawer) => { return this.drawer = drawer  }}
            keyboardDismissMode="on-drag"
            renderNavigationView={() => navigationView}>
            <View style={styles.container}>
 // Here is content component for drawer, need to refer drawer reference
            <DrawerScreen ></DrawerScreen>
            </View>
          </DrawerLayout>
        );
      }
    });

    var styles = StyleSheet.create({
      container: {
        alignItems: 'center',
        justifyContent: 'center',
        flex: 1,
        flexDirection: 'column',
      },
     });

    module.exports = DrawerLayoutExample;

DrawerScreen.js

'use strict';
var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Dimensions,
  Image,
  TouchableHighlight,
  TextInput,
} = React;

var deviceWidth = Dimensions.get('window').width;

var DrawerScreen = React.createClass({


  render: function() {
    return (

        <View style={styles.container}>

          <Text style={styles.welcome}>Content!</Text>

          <TouchableHighlight onPress={() => this.state.openDrawer()}>
            <Text>Open drawer</Text>
          </TouchableHighlight>
          <TextInput style={styles.inputField} />
        </View>
    );
  },

});

var styles = StyleSheet.create({
   container: {
      alignItems: 'center',
      justifyContent: 'center',
      flex: 1,
          flexDirection: 'column',
    },
    inputField: {
      backgroundColor: '#F2F2F2',
      height: 40,
    },
});

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

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

أعتقد أن السياق في هذه الحالة هو مكان أفضل لتخزينه ، لكن هذه المشكلة تمنعني من استخدامه.

wmertens ، هذا شيء يجب القيام به على componentDidMount ، أليس كذلك؟

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

لتغيير الحجم ، يمكنك الاستماع في componentDidMount ، أما بالنسبة للغات ، فسأعيد تصيير كل شيء

أفضل عدم تكرار كل منطق تغيير الحجم عندما يكون لدي شيء رائع مثل ملف
redux actioncreator الذي يستمع إلى apo بالكامل ويعمل من جانب الخادم
جدا…
لدي state.responsive.isPhone / isPrerender / screenwidth إلخ. على الخادم ،
أنا أرسل بناءً على وكيل المستخدم. أنيق.

في الجمعة ، 29 أبريل 2016 ، 4:52 مساءً Cyril Auburtin [email protected]
كتب:

لتغيير الحجم ، يمكنك الاستماع في componentDidMount ، للغات التي أحبها
إعادة تقديم كل شيء

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/facebook/react/issues/2517#issuecomment -215742327

ووت.
(مكتوب على الهاتف المحمول ، توجع العذر)

لكن نعم ، مفتاح بسيط = {lang} في الجزء العلوي من الشجرة يجب أن يكون كافياً
اللغات. ليس لطيفًا للمواقع ذات الرسوم المتحركة رغم ذلك.

في الجمعة ، 29 أبريل 2016 ، 6:07 مساءً Wout Mertens wout. كتب [email protected] :

أفضل عدم تكرار كل منطق تغيير الحجم عندما يكون لدي شيء رائع مثل ملف
redux actioncreator الذي يستمع إلى apo بالكامل ويعمل من جانب الخادم
جدا…
لدي state.responsive.isPhone / isPrerender / screenwidth إلخ
الخادم ، أرسل بناءً على وكيل المستخدم. أنيق.

في الجمعة ، 29 أبريل 2016 ، 4:52 مساءً Cyril Auburtin [email protected]
كتب:

لتغيير الحجم ، يمكنك الاستماع في componentDidMount ، للغات التي أحبها
إعادة تقديم كل شيء

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/facebook/react/issues/2517#issuecomment -215742327

ووت.
(مكتوب على الهاتف المحمول ، توجع العذر)

ووت.
(مكتوب على الهاتف المحمول ، توجع العذر)

كنت مثلك ، لكن مستمعي حدث تغيير الحجم رخيص في الواقع ، لا أعتقد أنه من السيئ أن يكون لديك العديد من المستمعين من نفس النوع

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

يوم الجمعة 29 أبريل 2016 الساعة 6:38 مساءً Cyril Auburtin [email protected]
كتب:

كنت مثلك ، لكن مستمعي حدث تغيير الحجم رخيص في الواقع ، لا أفعل
أعتقد أنه من السيئ أن يكون لديك العديد من المستمعين من نفس النوع

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/facebook/react/issues/2517#issuecomment -215797819

ووت.
(مكتوب على الهاتف المحمول ، توجع العذر)

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

للعمل مع Redux ، راجع https://github.com/reactjs/react-router/issues/470 ومناقشة مستمرة في العلاقات العامة.

في مرحلة ما ، سنقوم بالفعل بحل https://github.com/reactjs/react-router/issues/3484 لتسهيل استخدام المكتبات الأخرى ، ولكنه أصعب مما كنا نعتقد في الأصل.

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

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

بين الطريقتين ، على الأقل _ إلى حد ما_ عام على الرغم من ... أفضل ما يمكننا القيام به الآن على ما أعتقد 😛

نعم inded: P ، مع الإشارة فقط إلى أنه لا يزال دون المستوى الأمثل وليس بديلاً جيدًا لتحديد الطريقة التي يعمل بها السياق بشكل عام

jquense تعذر على المكون الموجود في المنتصف التصريح عن contextTypes للاستماع إلى كائن السياق من أعلى ، و childContextTypes / getChildContext() لتقديم نسخة معدلة من هذا السياق إلى نسله؟

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

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

@ 1000hz بالتأكيد ، لكنه كان يتحدث عن "تعديل أجزاء من السياق أثناء

DarylCantrell عفوًا ، لقد أخطأت في قراءة

لقد قدمت طلب سحب لهذه المشكلة: # 7213

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

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

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

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

مرحبًا bvella ، أعتقد أنك قصدت طلب السحب هذا: # 7213 ، وليس 7212.

DarylCantrell أنت على حق ، شكرًا

أعتقد أن https://github.com/facebook/react/pull/7213 / https://github.com/facebook/react/pull/7225 ، فكرة جيدة ويجب تكييفها

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

يجب أن يعمل إعلان ContextType لغرض التحقق فقط ، تمامًا مثل propTypes

مرة أخرى ، يرجى التفكير في الأمر لأنه يسبب لنا الكثير من المتاعب
(أنا أستخدم Relay Relay وإخفاء جميع كائنات السياق)

لقد علقت على https://github.com/facebook/react/pull/7225#issuecomment -276618328 ، بحجة أن السياق يجب فقط تحديث كل شيء ، و sCU يعمل فقط على تحديد ما إذا كان هذا المكون يحتاج إلى إعادة العرض ؛ سيتم التحقق من أبنائها بغض النظر.

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

هل يوجد أي حل الآن؟

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

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

تحقق من المناقشة: https://github.com/reactjs/rfcs/pull/2

acdlite حصل للتو على https://github.com/facebook/react/pull/11818.

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

ستكون واجهة برمجة التطبيقات الجديدة متاحة وموثقة في أحد إصدارات React 16.x الثانوية التالية.

gaearon لست متأكدًا مما إذا كنت تسمع هذا كثيرًا بما فيه الكفاية ، ولكن: يا رفاق تقومون بعمل رائع وأنا أقدر عملك. 🍺

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