React: دعم عرض الخادم غير المتزامن (انتظار البيانات قبل التقديم)

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

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

Component API Server Rendering Backlog Feature Request

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

قبل بضعة أشهر ، ألقيت حديثًا في JSConf Iceland الذي يصف ميزات العرض غير المتزامن القادمة في React (انظر الجزء الثاني): https://reactjs.org/blog/2018/03/01/sneak-peek-beyond-react -16.html. يتعلق هذا بجلب البيانات من جانب العميل.

الآن ألقى acdlite حديثًا حول كيفية تطبيق نفس المفاهيم لتمكين انتظار البيانات بشكل غير متزامن على الخادم في مكونات https://www.youtube.com/watch؟ z-6JC0_cOns

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

ال 139 كومينتر

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

هناك حالتان أجد صعوبة في حلهما بدون ذلك:

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

رد فعل غير متزامن يحل تلك المشاكل مع الألياف ، وذاكرة التخزين المؤقت. هذا هو الحيلة ولكن من وجهة نظري هذه مجرد حلول "غامضة" لحل مشكلة لا يمكن حلها إلا في جوهرها.

قم بتلويني دون علمي بهذا الموضوع ، componentWillMount غير متزامن ولا تُعيد أي شيء على الفور ، ما الذي يفترض أن تعرضه React حتى لا يوجد شيء؟ إذا كان الأمر كذلك ، فلماذا لا ترجع شيئًا في العرض إذا لم تكن هناك بيانات حتى الآن؟ (نعم أحصل على جانب الخادم) أيضًا ، ما الذي يجب أن يحدث إذا تغيرت الدعائم قبل إطلاق componentWillMount ؟

شخصيًا ، يبدو أنه من الخطأ إرسال الطلبات غير المتزامنة خلال componentWillMount ما لم يكن المكون حقًا صندوقًا أسود معزولًا ويقوم أيضًا بتنفيذ مؤشر تحميل. بقدر ما أفهمه ، لا ينبغي الخلط بين مكونات React وحالات OOP الأكثر تقليدية. في أفضل الأحوال ، يكون مكوِّن React أداة لتصور البيانات في الخاصيات ، إذا كانت تفاعلية ، فمن المحتمل أن تكون كذلك. إنها وجهة نظر وليست وجهة نظر ونموذج.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

لا أعتقد أن هذا النهج يعني التعامل مع المكون على أنه عرض ونموذج. إذا نظرت إلى بنية Flux ، فإنهم يفكرون في مكونات React على أنها _controller-views_ التي لا تعرض البيانات (من المتاجر) فحسب ، بل تستدعي أيضًا الإجراءات بناءً على تفاعلات المستخدم. وتقوم الإجراءات بتحديث المخازن بعد ذلك (= نموذج). بالنسبة لي ، يبدو الأمر وكأنه بنية MVC واضحة.

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

في هذه اللحظة ، يبدو لي أن الطريقة الوحيدة هي React-async / Fibers + Flux. الشيء الجميل في Flux هو أننا لا نحتاج إلى ذاكرة تخزين مؤقت مصطنعة لنقل حالات المكونات من الخادم إلى العميل (كما حدث في مثال رد الفعل غير المتزامن الأصلي) ، يمكننا ببساطة تهيئة المتاجر ثم إرسالها إلى العميل مع ترميز html (انظر هذا المثال ).

لكن هذا الحل هو في الواقع "قذر".

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

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

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

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

نعم ، سيكون ذلك جيدًا. حاليًا ، يمكن استخدام مكون العرض مرتين على جانب الخادم كحل بديل.

أريد أن أشير إلى رد الفعل-nexus كمثال على ما أريد أن أكون مدعومًا في React. إنها في الأساس إعادة كتابة لكيفية عمل mountComponent فيما عدا أنها تبني شجرة المكون دون تثبيتها فعليًا على DOM أو كتابة سلسلة. يتيح لك ذلك اجتياز شجرة المكون وإطلاق الطرق غير المتزامنة أثناء بناء الشجرة. تكمن المشكلة في هذا التطبيق كما هو ، في أنه يرمي تلك الشجرة الأولى بعيدًا ثم يستدعي React.renderToString أي حال ، في حين أنه سيكون من الجيد أخذ شجرة ما قبل التصيير وتصييرها / تحميلها.

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

mridgway إذا لم أكن مخطئًا ، فقد يكون ReactContext شيئًا متوافقًا وسيختفي في 0.14. لكني قد أكون مخطئا.

gaearon نعم ، هذا هو الإحساس الذي حصلت عليه من إهمال withContext.

: +1: استخدام react-router لهذا الصراف الآلي. يبدو نهج mridgway معقولاً للغاية.

هناك اختلاف طفيف في هذه المشكلة وهو كيفية التعامل مع التحميل غير المتزامن لأجزاء التعليمات البرمجية التي ينتجها المجمّع (مثل حزمة الويب).

كما تمت مناقشته في هذه التذكرة - https://github.com/rackt/react-router/issues/1402 - فإن مشكلة دعم العرض غير المتزامن هي أن العرض الأولي يبدو فارغًا لأن الأجزاء ذات الصلة لم يتم تحميلها بعد في الأول اجتياز التصيير ، ينتج عنه <noscript> في جذر DOM وفشل المجموع الاختباري. يتم وضع كل شيء في مكانه بسرعة بعد ذلك ، ولكنه ينتج عنه وميض في واجهة المستخدم عند العمل محليًا والأسوأ في هذا المجال ، خاصة إذا كانت الأجزاء المراد تنزيلها ذات حجم معقول (لنقل> 30 كيلوبايت)

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

anatomic هذه ليست مسؤولية

لا تتردد في تنفيذ استراتيجيات بديلة قد تناسبك بشكل أفضل ، قل <WaitFor for={MyAsyncLoadedCompSignal} until={...} then={() => <MyAsyncLoadedComp ... />} /> . لكن هذه الآراء ذات رأي وليست شيئًا يجب على React أو حتى تحتاج إلى تقديمه ، لذلك من الأفضل تركها للمجتمع.

من الأفضل إبقاء الأشياء غير المتزامنة خارج نطاق مكونات React ، وإليك مثال:

import React from 'react';
import Layout from './components/Layout';
import NotFoundPage from './components/NotFoundPage';
import ErrorPage from './components/ErrorPage';

const routes = {

  '/': () => new Promise(resolve => {
    require(['./components/HomePage'], HomePage => { // Webpack's script loader
      resolve(<Layout><HomePage /></Layout>);
    });
  }),

  '/about': () => new Promise(resolve => {
    require(['./components/AboutPage'], AboutPage => { // Webpack's script loader
      resolve(<Layout><AboutPage /></Layout>);
    });
  })

};

const container = document.getElementById('app');

async function render() {
  try {
    const path = window.location.hash.substr(1) || '/';
    const route = routes[path];
    const component = route ? await route() : <NotFoundPage />;
    React.render(component, container);
  } catch (err) {
    React.render(<ErrorPage error={err} />, container);
  }
}

window.addEventListener('hashchange', () => render());
render();

راجع تقسيم رمز Webpack وتوجيه React.js من Scratch وتوجيه الاستجابة (قريبًا)

syranide ، سأستمر في العمل بعيدًا ، لكنني لا أعتقد أنه ثنائي كما

إذا طبقنا نهج <WaitFor ... /> ، فسنستمر بالتأكيد في الحصول على DOM مختلف في العرض الأول والذي سيستمر في إحداث وميض / اختفاء المحتوى؟

إذا فعلنا ، بالتأكيد سنستمر في الحصول على DOM مختلف في العرض الأول والذي سيتسبب في وميض / اختفاء المحتوى؟

إذا كنت لا تريد وميض (البعض يفعل) ، فهذه مجرد مسألة انتظار تحميل جميع الأجزاء التي تعتمد عليها قبل العرض ، يوفر webpack هذا خارج الصندوق بـ require.resolve .

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

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

سأنظر في ذلك ، فهمت لـ require.resolve أنه كان بحثًا متزامنًا لمعرّف الوحدة النمطية ولم يتضمن رحلة إلى الخادم؟ نحن نستخدم require.ensure لإدارة تحميل الكتلة.

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

const history = new BrowserHistory();

if (typeof history.setup === "function") {
    history.setup();
}

Router.run(routes, history.location, (err, initialState, transition) => {
    React.render(<Provider redux={redux}>{() => <Router key="ta-app" history={history} children={routes} />}</Provider>, document.getElementById('ta-app'));
});

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

معذرة ، نعم قصدت require.ensure . لا يتم تنفيذ رد النداء إلا عند استيفاء جميع التبعيات ، لذا فإن الأمر يتعلق فقط بوضع render / setState بداخله.

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

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

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

لست على دراية تامة بجهاز التوجيه التفاعلي ، لكنني ما زلت أتخيل أنه مجرد حالة setRoute(...) => require.ensure([], function() { require(...); setRoute(...); }) وهي في الحقيقة ليست عملية لذا فأنت تقدم مستوى آخر من المراوغة. خريطة المسارات ومحمل require.ensure المتزامن لكل منهما. اكتب مساعدًا function asyncSetRoute(...) { loadRoute(route, function() { setRoute(...); }} ، يمكنك الآن الاتصال بـ asyncSetRoute بدلاً من ذلك ، وسوف يؤجل تحديث الموجه حتى يصبح كل شيء جاهزًا.

رمز زائف ونوع عام ، لكن يبدو أن هذا هو النهج العام بالنسبة لي. ربما يجب أن يوفر جهاز التوجيه هذا ، ربما لا ... ربما يتم توفيره بشكل مثالي كمساعد خارجي ، لست متأكدًا.

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

الحلول الممكنة على المدى القصير:
أ. املأ مخزنًا مسبقًا واجعل التحميل من جانب الخادم متزامنًا

ب. قم بتغذية كل شيء من الأعلى كمدخل بيانات واحد بعد جلب كائن بيانات واحد غير متزامن.

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

إعادة: "ب". في الأساس نفس المشكلة المذكورة أعلاه. هل يضطر الأشخاص إلى الاعتماد قليلاً على JSONs للذهاب مع كل من طرقهم؟

هل توجد أي حلول أخرى قصيرة المدى أثناء انتظار حل مدعوم من React؟ أي مستخدم لاند شوكات أو ملحقات؟ https://www.npmjs.com/package/react-async ؟

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

أنا لا أفهم المشكلة. :-(

  1. استخدم حاوية Flux أو Flux-like (Alt ، Redux ، Flummox ، إلخ) حيث لا تكون المتاجر مفردة.
  2. حدد طرقًا ثابتة مثل fetchData على معالجات المسار التي تعيد الوعود.
  3. على الخادم ، قم بمطابقة المسار مع المكونات ، واحصل على fetchData منها وانتظر حتى تكتمل قبل عرضها. سيؤدي هذا إلى ملء مثيل متجر Flux أو Redux. لاحظ أن نسخة المتجر ليست مفردة - إنها مرتبطة بطلب معين ، لذلك تظل الطلبات معزولة.
  4. عندما تكون الوعود جاهزة ، قم بالتقديم بشكل متزامن مع نسخة المتجر التي قمت بتعبئتها مسبقًا.

إليك برنامج تعليمي جيد لـ Redux يصف هذا النهج: https://medium.com/@bananaoomarang/handcrafting -an-isomorphic-redux-application-with-love-40ada4468af4

gaearon أعتذر إذا كنت في حيرة من

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

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

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

NickStefan مع إعادة التوجيه ، على سبيل المثال ، يبدو جلب البيانات غير المتزامنة كما يلي:

import Router from 'react-routing/lib/Router';
import http from './core/http';

const router = new Router(on => {
  on('/products', async () => <ProductList />);
  on('/products/:id', async (state) => {
    const data = await http.get(`/api/products/${state.params.id`);
    return data && <Product {...data} />;
  });
});

await router.dispatch('/products/123', component => React.render(component, document.body));

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

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

حلمي هو أنه في يوم من الأيام سنكون قادرين على كتابة CMS كامل باستخدام React ، شيء مثل Wordpress أو Drupal أو Modx. ولكن بدلاً من مقتطفات HTML / PHP ، سننشئ موقع الويب من مكونات React.

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

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

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

ليس بالضبط في الجذر — عند مستوى معالج المسار. قد يكون هناك العديد من معالجات التوجيه في تطبيقك. علاوة على ذلك ، تدعم مكتبات مثل React Router معالجات التوجيه المتداخلة . هذا يعني أن معالج المسار المتداخل الخاص بك يمكنه تحديد تبعية ، وستحتوي مطابقة الموجه على مجموعة من معالجات التوجيه الهرمية المتطابقة ، بحيث يمكنك Promise.all لهم. هل لهذا معنى؟

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

نهج "يمكن لكل مكون إعلان تبعية" ليس عمليًا إلا إذا كان لديك نوع من حل تجميع الطلبات. تخيل لو أن <User> أعلن أنه يحتاج إلى استدعاء API ، والآن تقوم بعرض قائمة من 100 <User> s - هل تريد انتظار 100 طلب؟ لا يعمل هذا النوع من تفاصيل متطلبات جلب البيانات إلا عندما يكون لديك حل تجميع للطلب. إذا كان هذا يناسبك ، فإن Relay هو ذلك بالضبط. لكنك ستحتاج إلى خلفية خاصة لذلك.

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

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

نهج "يمكن لكل مكون إعلان تبعية" ليس عمليًا إلا إذا كان لديك نوع من حل تجميع الطلبات.

بعد مزيد من التفكير في هذا الأمر ، أتفق معك. ما كنت أبحث عنه ليس عمليًا في الواقع.

في الأصل كان لدي فكرة أنه حتى 100 الخاص بكومثال على ما يرام مع الانضباط فريق (أي جعل مجرد <UsersContainer> أن يفعل 1 طلب للجميع 100). لكن هذا ليس "قابلاً للتطوير" لمجرد الحصول على اتفاقية. من المحتمل أن يكون من الأفضل فرض جميع التبعيات على الجذر أو جهاز التوجيه. حتى نوع الترحيل يجبرك على إعلان التبعيات في الجذر بحاوياته الثلاثة المختلفة (RelayContainer ، RelayRootContainer ، RelayRouter ، إلخ). إنه نوع من إثبات النقطة التي مفادها أن الطريقة الوحيدة بشكل أساسي هي "رفع" إعلانات التبعية الخاصة بك إلى أعلى الشجرة.

أهلا!
هل هناك أي تحديثات على هذا؟

+1

أؤكد أنه إذا كنت تفكر حقًا في هذا ، فأنت لا تريد القيام بذلك. اعتقدت في الأصل أنني أردت أن تقوم React بعمل عرض غير متزامن. لكن آخرين في هذا الموضوع أقنعوني بخلاف ذلك.

حتى في Relay ، عليك أساسًا "رفع" التبعيات الخاصة بك إلى أعلى الشجرة بإعلانات حاوية الجذر وحاويات الترحيل وما إلى ذلك.

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

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

في الواقع يعود الأمر للخلف لجعل طريقة العرض تحدد البيانات المراد تحميلها.

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

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

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

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

لم أقرأ الموضوع بأكمله آسف إذا تمت مناقشة هذا بالفعل.

أحد الأشياء التي من شأنها أن تساعد حقًا هو إذا كانت هناك طريقة react-dom/server شأنها فقط "بدء / إنشاء" أحد المكونات وتنشيط طرق دورة الحياة ولكن دع المطور يقرر متى يكون جاهزًا لتقديم المكون إلى سلسلة html . على سبيل المثال ، يمكن للمطور استخدام setTimeout أو شيء أكثر موثوقية لانتظار اكتمال الطرق غير المتزامنة.

هذا هو "الاختراق" الذي أستخدمه مع redux في الوقت الحالي لتحقيق ذلك:

  // start/instantiate component
  // fires componentWillMount methods which fetch async data
  ReactDOM.renderToString(rootEle)

  // all my async methods increment a `wait` counter 
  // and decrement it when they resolve
  const unsubscribe = store.subscribe(() => {
    const state = store.getState()
    // as a result, when there are no more pending promises, the wait counter is 0
    if (state.wait === 0) {
      unsubscribe()
      // all the data is now in our redux store
      // so we can render the element synchronously
      const html = ReactDOM.renderToString(rootEle)
      res.send(html)
    }
  })

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

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

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

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

const virtualTree = ReactDOM.renderVirtual(rootEle);

// get the bundled query from redux store for example
const bundle = store.getState().bundle;

// Fetch the data according to the bundle
const data = fetchDataSomehow(bundle);

// hydrate store
store.dispatch({type: 'hydrate', data});
// components that should update should be marked on the virtual tree as 'dirty'

virtualTree.update(); // this would only update the components that needed update

const domString = virtualTree.renderToString(); // final result

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

ماذا تظنون يا جماعة؟ هل هناك شيء يجب مراعاته أو أراه خاطئًا تمامًا؟

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

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

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

  • هل دولتك لديها معايير مختلفة بشكل مستقل؟ تمثيلهم كمعلمات استعلام منفصلة.
  • هل حالتك (أو جزء منها) أكبر من أن تتناسب مع عنوان URL؟ قم بتسميته وتخزينه في مخزن بيانات غير قابل للتغيير. الرجوع إليها بالاسم / المعرف.
  • هل تتغير حالتك بسرعة بحيث لا يمكنك تخزينها بالكامل إلى الأبد؟ تهانينا ، لديك بيانات ضخمة شرعية ، تنطلق للتخزين وتبدأ في التفكير في أشياء ذكية لتفعلها بها. أو ، يمكنك أن تتجنب ، وتحوير بياناتك فقط باستخدام استعلامات UPDATE ، وتقبل أنه لا يمكنك تخزين كل الأشياء مؤقتًا إلى الأبد لاحقًا (*).
  • هل لديك طرق عرض مختلفة لمستخدمين مختلفين ، ولكن يتم تقديمها على نفس عنوان URL ، على سبيل المثال ، صفحة رئيسية مخصصة؟ انتقل عند تعريف المستخدم إلى عنوان URL يتضمن معرف المستخدم.
  • هل تقوم بالبناء فوق تطبيق قديم ، حيث لا يتوفر لديك خيار كسر بنية عنوان URL القديمة؟ هذا مؤلم ، أنا في نفس القارب. أعد توجيه بنية عنوان URL القديمة إلى بنية عنوان URL تمت هندستها جيدًا ، وترجمة بيانات الجلسة (أو أي شيء آخر) إلى شرائح ومعلمات مسار URL.
  • هل لديك سيطرة قليلة أو معدومة على بنية التطبيق الخاص بك؟ ليست هذه هي الحالة التي تم تصميم React من أجلها ، ولا نريد أن تتشوه React لجعلها تتلاءم مع شيء مثل هندسة Wordpress / Magnolia / Umbraco المتوافقة بشكل متبادل.

ما الذي تحصل عليه مقابل كل هذا العمل ، والذي لم يكن لديك لولا ذلك؟

  • قدرة مستخدم واحد على إحضار مستخدم آخر إلى نفس المكان مثله في التطبيق ، من خلال مشاركة عنوان URL.
  • القدرة على التنقل في التطبيق باستخدام جميع الأدوات التي يوفرها المتصفح. العميل القياسي في عنصره.
  • القدرة على تقديم ترقيم صفحات معقد بطريقة يسهل على العميل اتباعها: رابط next في الرد. تعد واجهة برمجة تطبيقات الرسم البياني FB مثالًا رائعًا على ذلك.
  • رسم بياني مفصل لسير عمل المستخدم في Google Analytics.
  • خيار إنشاء الرسم البياني المذكور بنفسك من لا شيء سوى طلب السجلات.
  • هروب من مسار الفوضى النجمي: بدلاً من مطابقة جميع الطلبات كـ app.get("*", theOneTrueClientonaserverEntryPoint) ، يمكنك استخدام إطار عمل تطبيق الخادم الخاص بك كما كان مقصودًا. يمكنك إرجاع رموز حالة HTTP الصحيحة من الطلبات ، بدلاً من 200 OK\n\n{status: "error"} . طريق النجوم مغري ، لكنه يقود إلى الجنون.

والآن بعد أن أصبحت أداة React ، أداة النجوم لدينا ، لا تتحكم في العملية ، كيف نحصل على بياناتنا؟ كيف نعرف ما هي المكونات التي يجب تقديمها؟

  1. قم بالتوجيه إلى وظيفة الوصول إلى البيانات وجلب البيانات لمعلمات الطلب ذات الصلة. كرر ذلك حتى تنتهي من تحليل عنوان URL بالكامل ويكون لديك كائن سياق كامل.
  2. حوِّل السياق إلى أبسط كائن استجابة ممكن ، كما لو كنت ستستجيب لطلب واجهة برمجة التطبيقات. هل تقدم طلب API؟ ثم انتهيت وجاف.
  3. قم بتمرير هذا الكائن المعقد البسيط ، ولكن من المحتمل أن يكون كبيرًا ، إلى مكون المستوى الأعلى. من هنا ، يكون تكوين مكون React على طول الطريق.
  4. تجسيد لسلسلة ، والاستجابة. دع CDN يعرف أنه يمكنه تخزين هذا مؤقتًا إلى الأبد (* ما لم تضحي بهذا الخيار أعلاه) ، لأن CDN يتم تحديده من خلال عناوين URL ، وجميع حالاتك لها عنوان URL. بالتأكيد ، لا تحتوي شبكات CDN على مساحة تخزين غير محدودة ، لكنها تعطي الأولوية.

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

هذا ما يجعل React رائعة: إنها الرؤية. أفضل منظر. فقط الرأي. λ

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

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

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

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

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

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

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

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

:بيرة:

ملاحظة: لم أقصد الإشارة إلى أن HTTP سيكون بروتوكول اتصال جيد لـ MMOFPS

@ d4goxn أنا أتفهم تمامًا

أعتقد أن هذا المستوى من التجريد هو السبيل للذهاب. لقد كنت أستخدمه في Relax CMS وسير العمل والعزلة هي نعمة للعمل معها. ليس هذا فقط ولكن البيانات المطلوبة ليست أكثر ولا أقل ما تحتاجه واجهة المستخدم ، ويتم ذلك تلقائيًا عن طريق جمع البيانات التي يحتاجها كل مكون ودمجها. يتم ذلك عن طريق Relate http://relax.github.io/relate/how-it-works.html إذا كنت مهتمًا بالتحقق. باستخدام هذا ، يمكنني أيضًا تضمين أي مكون في أي مكان في تطبيقي والتأكد من أنه سيعمل ككتلة مستقلة لتطبيقي.

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

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

بالنسبة لي ، السؤال الرئيسي هو كيفية بناء مثل هذه الوظيفة .

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

لست معتادًا على Spring MVC ، لكنني كثيرًا ما أستخدم إطار عمل MVC آخر (إطار PHP يسمى Nette) والذي يعالج هذه المشكلة بطريقة مشابهة جدًا للطريقة التي أرغب في استخدام React. يدعم هذا الإطار أيضًا المكونات. الفكرة هي أنه بالنسبة لكل مكون (على سبيل المثال نموذج) ، فإنك تحدد مصنعًا في الكود الخاص بك يكون مسؤولاً عن إنشاء مثيل للمكون وخاصة عن _تحميل جميع البيانات الضرورية_. يمكن بعد ذلك تضمين هذا المكون في أي مكان في العرض. لذلك أثناء كتابة كود HTML وإنشاء _عرض التسلسل الهرمي_ ، يمكنك ببساطة إدخال مكون وسيتولى المصنع الأساسي التهيئة اللازمة. يتصرف المكون مثل وحدة تحكم مستقلة صغيرة ، وله دورة حياته الخاصة ، ويتعامل مع تبعياته ويمكن حتى تحديد معالمه من العرض مما يزيد من قابليته لإعادة الاستخدام.

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

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

  • الأداة الأساسية هي جهاز التوجيه التفاعلي . يسمح بربط طلب البيانات غير المتزامن على كل عنوان URL ويعمل من جانب العميل ومن جانب الخادم. من الناحية الرسمية ، يعاني هذا النهج من المشكلة التي ذكرتها سابقًا. هذه المكونات _controller_ غير ممكنة. ولكن ما يهم هنا هو تصميم react-router . يسمح بتعريف كل من _data-hierarchy_ و _ view / component hierarchy_ في نفس المكان كما أن تعريفات المسار الفعلية تكون هرمية أيضًا. إنه شعور يشبه رد الفعل للغاية.
  • يتم التعامل مع الحالة بأكملها (البيانات) مع الإعادة . إلى جانب جميع المزايا الأخرى ، فإنه يحافظ على الحالة بأكملها في كائن واحد مما يعني أنه من السهل جدًا والطبيعي إنشاء الكائن على الخادم وإرساله إلى العميل. أيضًا بفضل نهج connect() ، ليس من الضروري تمرير جميع البيانات من المستوى الأعلى لأسفل باستخدام الدعائم (سيكون ذلك جنونيًا تمامًا بالنظر إلى الحجم الحالي لطلبي).
  • قطعة أخرى من اللغز هي إعادة تحديدها مما يسمح لنا بإبقاء الحالة صغيرة قدر الإمكان. وأيضا يزيد بشكل كبير من عامل الفصل.

لا يزال هذا غير مثالي ولكنه تقدم كبير عما كان متاحًا عندما صادفت هذا الموضوع لأول مرة. يمكن العثور على تنفيذ العينة هنا .

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

في الوقت الحالي ، أردت فقط أن أؤيد الأهمية المتزايدة لهذا التفاعل المتماثل ، IMO. سأحاول إيجاد حل في هذه الأثناء. شكرا.

decodeman في حال كنت مهتمًا ، بالنسبة لـ Relate ، لقد قمت بأدنى حد من عبور التفاعل للحصول على تبعيات البيانات من المكونات https://github.com/relax/relate/blob/master/lib/server/get-data -ترابطات. بهذه الطريقة يمكنني الحصول على جميع تبعيات البيانات -> جلب البيانات -> الرد على السلسلة.

decodeman ، FWIW لقد استخدمنا أسلوب العرض المزدوج (مثل ما تلمح إليه) بنجاح في تطبيق إنتاج كبير. إنه مستوحى من مثال redux-saga هذا ، ولكن يجب أن يعمل النهج العام جيدًا مع أي نوع من التحميل غير المتزامن. تحتاج فقط إلى نقل التحميل إلى componentWillMount . للمساعدة في إبقائه قابلاً للإدارة ، لدينا أيضًا مكونات ذات ترتيب أعلى تهتم بسيناريوهات التحميل الشائعة (على سبيل المثال ، تحقق من prop x وقم بالتحميل إذا لم يكن هناك شيء.

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

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

وقد تم حل هذا يسمى تدفق تدفق رد فعل.

يوم الخميس 3 نوفمبر 2016 ، فلوريان كراوثان [email protected]
كتب:

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

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

-
أنت تتلقى هذا لأنك مشترك في هذا الموضوع.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/facebook/react/issues/1739#issuecomment -258198533 ،
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/ATnWLUIEJw4m1Y3A4oGDOBzP6_ajDcqIks5q6g4_gaJpZM4CHAWq
.

@ yamat124 إذا كنت أبحث عن تيار رد الفعل أجد هذا المشروع فقط: https://github.com/aickin/react-dom-stream

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

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

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

يحتوي Next.js على async getInitialProps للقيام بالعرض من جانب الخادم ، ولسوء الحظ ما زلت بحاجة إلى استدعاء الطفل getInitialProps من الوالدين طوال الطريق إلى الجذر. يسمح عميل Apollo GraphQL أيضًا باجتياز كل الشجرة لجمع متطلبات البيانات من جانب الخادم ثم إرسال كل شيء مرة أخرى. مثال على التالي + أبولو: https://github.com/sedubois/realate.

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

لقد تعلمت للتو عن SSR هذا الأسبوع ، أتمنى أن يكون ما أكتب منطقيًا 😄

/ سم مكعبnkzawastubailo

راجع للشغل componentWill/DidMount غير متزامن بالفعل ، هل يساعد ذلك؟

https://twitter.com/Vjeux/status/772202716479139840

sedubois هل تنتظر

olalonde يبدو كذلك: https://github.com/sedubois/react-async-poc/blob/1d41b6f77e789c4e0e9623ba1c54f5ed8d6b9912/src/App.js

const getMessage = async () => new Promise((resolve) => {
  setTimeout(() => {
    resolve('Got async message!');
  }, 3000);
});
class App extends Component {
  state = {
    message: 'Loading...',
  };
  async componentWillMount() {
    this.setState({ message: await getMessage() });
  }
  render() {
    return (... {this.state.message} ...);
  }
}
loadinggot

sedubois لاحظ أنه في المثال الخاص بك ، componentWillMount

  async componentWillMount() {
    this.setState({ message: await getMessage() });
  }

تعيد undefined ووعدًا ، لكن لقطات الشاشة تُظهر أن React لا تنتظر (لا يمكنها) الوعد ، لأنها تقدم النص Loading... .

تحرير: مصحح.

seduboispolytypic سيؤدي أيضًا إلى تجاهل جميع الأخطاء التي يتم إلقاؤها داخل الوظيفة بصمت ، نظرًا لعدم معالجة الوعد على الإطلاق.

polytypic @ dantman لست متأكدًا تمامًا من المقصود بعبارة "لم يتم التعامل مع الوعد على الإطلاق". ينتظره عامل التشغيل await . تحتاج إلى محاولة اكتشاف الخطأ ، لقد قمت بتحديث المثال (باستخدام توقيع التحميل / الخطأ على غرار ما يفعله Apollo).

    try {
      this.setState({ message: await getMessage() });
    } catch(error) {
      this.setState({ error });
    }

وتقديم:

{error ? error : loading ? 'Loading...' : message}
screen shot 2016-11-07 at 13 25 46

sedubois عندما تقوم async a فإنها تقوم ضمنيًا بإرجاع وعد ، أي throw في الوظيفة يتحول ضمنيًا إلى رفض لهذا الوعد بدلاً من طرح المكدس. هذا يعني أن componentWillMount الآن يعيد الوعد للمتصل به.

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

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

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

sedubois في الواقع ، يبدو دائمًا أن الطريقة غير المتزامنة تعطي وعدًا في JavaScript (حسنًا ، JavaScript في المستقبل). كنت في حيرة من أمري وأنا أفكر في مشكلات الانتظار غير المتزامن في C #. _اسفار على الضوضاء! _

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

بفضلpolytypicdantman 👍 نعم، هناك حاجة لإجراء تغييرات على يقين داخل لرد على الانتظار لأخطاء الاستجابة والتعامل بشكل صحيح. ربما يمكن إضافة بعض await هنا وهناك في الكود الخاص به 😄

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

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

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

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

يعجبني ما اقترحه fkrauthan . طريقة دورة الحياة load والتي يمكنها إرجاع وعد أو undefined renderToStringAsync ووظيفة load على العميل وعلى الخادم. إذا استخدمنا render أو renderToString ، يتم تجاهل الوعد المرتجع ليتناسب مع السلوك الذي لدينا اليوم. إذا استخدمنا renderToStringAsync و load يُرجع الوعد ، يجب الوفاء بالوعد قبل تقديمه.

لماذا لا تحب Next.js ، أضف دالة دورة حياة async getInitialProps والتي يتم استدعاؤها قبل المنشئ؟ إذا لم يكن هناك مثل هذا الأسلوب ، فاتصل بالمُنشئ مباشرة.

const props = await (Component.getInitialProps ? Component.getInitialProps(ctx) : {});
...
const app = createElement(App, {
  Component,
  props,
  ...
});

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

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

أعتقد أن فكرة @ Lenne231 قد تسبب بعض المشاكل حيث قد

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

الأشخاص الذين يستخدمون ES6 ليس لديهم / يستخدمون هذه الطريقة

fkrauthan ربما تشير إلى getInitialState ؟ كنت أتحدث هنا عن اسم جديد ، getInitialProps (الاسم المستخدم في Next.js).

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

sedubois حتى هذا واحد. أستخدم على سبيل المثال ميزة es7 وحدد static props = {}; في جسم صفي. هذا يجعل طريقة الكود أجمل للقراءة في رأيي وأنا متأكد من أن المزيد والمزيد من الناس سوف يتحولون إلى ذلك بمجرد إصدار es7 رسميًا.

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

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

لقد ذكرت من قبل ولكن واجهة برمجة التطبيقات الجيدة ستكون شيئًا مثل ما يلي (مع تحديث بسيط مع ما اقترحته من قبل):

const virtualTree = ReactDOM.renderVirtual(rootEle);

// get the bundled query from redux store for example
const bundle = store.getState().bundle;

// Fetch the data according to the bundle
const data = await fetchDataSomehow(bundle);

// hydrate store (this will set updates on the virtual tree)
store.dispatch({type: 'hydrate', data});

// final result
const domString = virtualTree.renderToString();

سيؤدي هذا إلى تجنب المشكلة التي يواجهها بعض عملاء GraphQL مثل Apollo والتي تفرض عليهم عمل عرض مزدوج لـ RenderToString. كونك أول من جلب تبعيات البيانات ، والثاني يجلب البيانات التي تم ملؤها. أعتقد أن هذا مضيعة للمعالجة نظرًا لأن renderToString مكلفًا للغاية.

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

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

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

يجعل كل شيء أكثر تعقيدًا.

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

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

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

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

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

أعتقد أنه يمكننا إضافة دالة "renderToStringAsync" لتفاعل دوم / خادم. سيكون الاختلاف عن العرض العادي لـ renderToString أنه يُرجع وعدًا.

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

لذلك إذا كان لدينا مثال هيكل التطبيق التالي:

    ComponentB
    ComponentC
        ComponentD
        ComponentE

ستكون العملية:

1) instanciate componentA
2) await componentA.initialize();
3) componentA.render()
4) do in parallel(
    instanciate componentB, await componentB.initialize(), componentB.render()
    instanciate componentC, await componentC.initialize(), componentC.render(), do in parallel(
        instanciate componentD, await componentD.initialize(), componentD.render()
        instanciate componentE, await componentE.initialize(), componentE.render()
    )
)
5) render to string

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

VanCoding لديه نفس الفكرة التي كنت أفكر فيها منذ فترة. كنت أتساءل عما إذا كان يمكن أيضًا استدعاء التهيئة تلقائيًا في componentDidMount على العميل؟

لذلك على الخادم سيكون:

initialize()
render()

وعلى العميل سيكون:

render() // without data (unless available synchronously)
componentDidMount()
initialize()
render() // with data

لدي تطبيق عملي لعرض خادم التفاعل باستخدام جهاز التوجيه التفاعلي v4 ، وتفاعل أبولو مع GraphQL.

كان مستوحى من جانب الخادم - التقسيم - الكود - وإعادة التحميل - مع جهاز التوجيه التفاعلي .

يستخدم عرض الخادم أساسًا مكونًا متزامنًا ، ويستخدم عرض العميل مكونًا غير متزامن بحيث يتم تحميل حزمة الويب غير المتزامنة وتنفيذ جافا سكريبت للوحدة النمطية.

بالمناسبة ، يتم تنفيذ عرض الخادم باستخدام Nashorn Script Engine (JVM).

رمز تقديم العميل
https://github.com/shendepu/react-ssr-starter-kit/blob/apollo/src/main.js#L63 -L82

كود تقديم الخادم
https://github.com/shendepu/react-ssr-starter-kit/blob/apollo/src/main.js#L128 -L155

يوجد مكان واحد مهم للتمييز بين المكونات المتزامنة أو غير المتزامنة في المسار.
مكون متزامن في الطريق
https://github.com/shendepu/react-ssr-starter-kit/blob/apollo/src/routes/Counter/Route.js#L10

المكون غير المتزامن في RouteAsync
https://github.com/shendepu/react-ssr-starter-kit/blob/apollo/src/routes/Counter/RouteAsync.js#L7 -L23

ملحوظة: اسم الملف يجب أن يكون Route.js أو RouteAsync.js. يجب أن يقوم الكود دائمًا باستيراد RouteAsync.js. سيقوم Webpack باستبداله بـ Route.js إذا كان مصممًا لعرض الخادم.
https://github.com/shendepu/react-ssr-starter-kit/blob/apollo/build/webpack.config.js#L72 -L80

لذلك سيكون هناك إصداران من الإصدار dist و dist_ssr و dist للعميل بينما dist_ssr للخادم الذي يحتوي على جزأين فقط: البائع والتطبيق . يتم تصدير حالة المتجر وتضمينها في <script> من index.html كـ __INITIAL_STATE__ . سبب وجود نسختين من الإصدار هو ReactDomServer.renderToString() لا يدعم المكون غير المتزامن حتى الآن.

المشكلة الوحيدة في نهج الإصدارين-build هي أن هناك تحذيرًا في وضع dev:
React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:

ولكن نظرًا لأن الاختلاف الوحيد بين إصدار العميل والخادم هو Route.js و RouteAsync.js ، لذلك يمكن تجاهل التحذير ، لا يظهر التحذير في وضع الإنتاج.

لجلب البيانات غير المتزامن قبل عرض المكون على جانب الخادم:

  • Rest API: تمت إضافة بيانات تحميل ثابتة في استخدام المكون
const { matchedRoutes, params } = matchRoutesToLocation(rootRoute.routes, 
                                                        location, [], {}, rootRoute.pattern)
matchedRoutes.filter(route => route.component.loadData).map(route =>
              route.component.loadData(store, params))

للتحقيق وتنفيذ loadData . matchedRoutes هي مجموعة من المسارات المتطابقة الأصل من الفهرس 0 . loadData بالتتابع أو بالتوازي.

  • استعلام GraphQL: ما عليك سوى استخدام getDataFromTree من react-apollo/server لتنفيذ جميع استعلامات GraphQL.

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

لقد كذبت أن التطبيق يحتوي على كود src فقط. يحتوي أيضًا على babel-runtime وتكرار core-js/library المشار إليه بواسطة babel-runtime . لا يمكن نقل babel-runtime إلى مجموعة البائعين نظرًا لعدم احتوائها على index.js أو إدخال رئيسي ، لذلك لا يمكن لحزمة الويب التعرف عليها كوحدة نمطية. لكن حجم الكود صغير.

دعونا نزيد من https://github.com/facebook/react/issues/1739#issuecomment -261577586

ربما لا تكون التهيئة اسمًا جيدًا - يجب أن يوضح الاسم نوعًا ما أنه من المفترض استخدامه فقط على الخادم ، أو في بيئة يتم فيها تأخير العرض حتى عودة هذه الوظيفة - ويعرف أيضًا باسم ليس في العميل. الأفكار: getStaticProps ، getServerProps ، getInitialProps ، getAsyncProps ...

سيكون من الجيد أيضًا أن نسمع من الفريق الأساسي ما إذا كانت هناك عوائق فنية أو غير ذلك من العوائق التي تحول دون تطوير طريقة RenderToStringAsync.

nmaro حسنًا ، أعتقد أن الوظيفة لا يجب أن تعيد أي شيء ، لذلك أفضل اسمًا لا يبدأ بـ "get" ، ولكن بصرف النظر عن هذا ، ما زلت أعتقد أن هذه ستكون أفضل طريقة. لا أمانع كيف يتم تسميتها في النهاية.

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

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

بدلاً من ذلك ، يمكننا إضافة خيار لـ renderToString ، كما في
renderToString(Component, {async: true})

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

VanCoding هل لديك مثال على كيفية استخدام التعليمات البرمجية الخاصة بك كطرف ثالث lib؟

تضمين التغريدة لكن بصراحة ، أعتقد أنه سيكون من الصعب دمج ذلك في خوارزمية التقديم الداخلية للتفاعل. تحقق من https://github.com/facebook/react/blob/master/src/renderers/dom/stack/server/ReactServerRendering.js وتضيع في العناصر الداخلية للتفاعل ... IMO نحتاج حقًا إلى رأي من شخص ما من النواة.

sedubois ، يمكنك استخدام الوظيفة كما لو كنت تستخدم وظيفة renderToString العادية. لكنه يعيد وعدًا يحل إلى سلسلة ، بدلاً من إرجاع سلسلة مباشرة.

لذا فإن استخدامه سيبدو كما يلي:

var react = require("react");
var renderAsync = require("react-render-async");
var MyComponent = require("./MyComponent");

renderAsync(react.createElement(MyComponent,{some:"props"}).then(function(html){
    console.log(html);
});

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

nmaro أنت بخير. سيكون ذلك مفيدًا.

ما هو الوضع على هذا؟

firasdib ما زلنا ننتظر رد بعض المطورين للتعليق ، على ما أعتقد.

+1

تتطلب مشكلات فهرسة Google SSR وجميع الأشياء الموصوفة أدناه يجب أن نتعامل معها ، وبالتالي فإن هذه المشكلة مهمة جدًا لنجاح React كمكتبة عامة.

أعتقد أن العرض غير المتزامن بالكامل ليس ضروريًا إذا قدمت JavaScript طريقة مناسبة لانتظار الوعد. ثم يمكننا تمرير معلمة تشير إلى الطقس أو لا نريد أن يكون تحميل البيانات متزامنًا (لـ SSR) أو غير متزامن (لمتصفح الويب الحقيقي). يمكن أن يبدأ منطق تحميل البيانات في الوعد في مُنشئ أي مكون من مكونات React ويمكن أن يتم الانتظار في componentWillMount.

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

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

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

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

  • سيتم تقديم DOMtree عدة مرات. إنه مثل نظام حي "يستقر" من حالة تحميل البيانات غير المستقرة إلى حالة "تحميل" مستقرة.
  • هناك خطر من أن النظام لن يصل إلى حالة "تحميل" مستقرة في نظام عربات التي تجرها الدواب. يجب تقديم الوقت المستقطع للتعامل معها.

والنتيجة هي استخدام أكثر "للحوسبة المكثفة" للمكتبة على جانب الخادم مع عملية ليست سريعة.

وبالتالي ، ما زلت أفكر في حل بديل من شأنه المساومة على الحالة العامة لصالح إنجاز الأمور :)

في غضون ذلك ، يتعين علينا حل SSR في بيئة تحميل البيانات غير المتزامنة.

  1. يجب اشتقاق مكالمات تحميل البيانات من عنوان URL للطلب (جهاز التوجيه التفاعلي مثال). اجمع كل وعود تحميل البيانات في قائمة واحدة من الوعود.
  2. استخدم Promise.all () ، وهو بحد ذاته وعد. عند اكتمال هذا الوعد ، قم بتمرير البيانات المحملة إلى وظيفة عرض الخادم.

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

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

لا أرى كيف يمكن جعل SSR للعمل في المشروع المعقد دون تكرار المنطق المكتوب بالفعل في دالة render (). قد يكون الجريان حلاً ، لكنني لم أجربه للتأكد.

تنفيذ العنصر رقم 1 غامض. في مثال جهاز التوجيه التفاعلي ، يتعين علينا كجهاز توجيه لإرجاع مكونات المستوى الأعلى التي تنتمي إلى هذا المسار إلينا. أعتقد أنه يمكننا إنشاء مثيل لهذه المكونات:

app.use(function(req, res, next) {
    match({ routes, location: req.url }, (error, redirectLocation, renderProps: any) => {
    if (error) {
        res.status(500).send(error.message)
    } else if (redirectLocation) {
        res.redirect(302, redirectLocation.pathname + redirectLocation.search)
    } else if (renderProps) {
        // You can also check renderProps.components or renderProps.routes for
        // your "not found" component or route respectively, and send a 404 as
        // below, if you're using a catch-all route.
        console.log("renderProps", renderProps)
        for (let eachComp of renderProps.components) {
            // create an instance of component
            // ask component to load its data
            // store data loading promise in a collection
            console.log("eachComp: ", eachComp)
        }
        res.status(200).send(renderToString(<RouterContext {...renderProps} />))
        } else {
        res.status(404).send('Not found')
        }
    })
});

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

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

هذا ما أراه.

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

من React Conf هذا الأسبوع ، بعد انتهاء React Fiber (React 16) ، يخططون للعمل على ما يلي (المفترض لـ React 17):

screen shot 2017-03-16 at 15 55 51

هل يعني أن طرق دورة حياة التفاعل غير المتزامن يمكن أن تأتي؟

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

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

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

https://github.com/siddharthkp/reaqt

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

siddharthkp أنا لا أرى حقًا ما يحاول المكون الخاص بك حله؟ إذا كان يدعم فقط asyncComponentWillMount لمكون Top Level Application React ، فلماذا يجب علي استخدام مكتبتك على الإطلاق؟ يمكنني حل هذا الوعد بالخارج ثم استدعاء التقديم؟ أو هل فاتني شيء؟

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

يمكنني حل هذا الوعد بالخارج ثم استدعاء التقديم؟

أنت على حق ، هذا بالضبط ما يفعله.

النداء هو أنك تحصل على غير متزامن ssr (+ تقسيم الكود + hmr) بأمر واحد. لقد رأيت الكثير من الأشخاص لا يطبقون SSR لأنه ليس سهلاً للغاية ، وكان هذا هو الدافع.

وهو يدعم فقط asyncComponentWillMount لمكون التطبيق عالي المستوى

  1. لا يحتوي على مكون تطبيق واحد. يمكنك جلب البيانات لكل صفحة / شاشة / نقطة دخول. (الترويج لنقاط دخول متعددة هنا )

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

siddharthkp كيف يتحسن الريبو الخاص بك عن Next.js (الذي تم تقديمه أيضًا في React Conf BTW)؟

https://github.com/zeit/next.js

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

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

أنا أتفق تماما. يمكن مناقشة أسئلة محددة في قضايا العقارات

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

const AsyncUser = props => fetchUser()
  .then(data => (
     <User {...data} />
   ))

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

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

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

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

إنه مفيد حقًا لتحميل البيانات - إلى حد كبير حالة الاستخدام التي كتبتها لحلها. حاول! 😄

https://github.com/davnicwil/react-frontload

<AsyncComponent 
  delayRendering={LoadingComponent}
> 
   {/*return a promise that returns a component here*/}
</AsyncComponent>

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

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

توصلت إلى تطبيق https://github.com/timurtu/react-render-async

واجهة مكون غير متزامنة لطيفة جدًا ،timurtu.

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

  • أولاً ، بالنظر إلى SSR ، أعتقد أن جلب البيانات على مستوى المسار هو الأكثر منطقية - وإليك السبب:
    إحضار بيانات جهاز Redux-First Router: حل حالة استخدام 80٪ للبرامج الوسيطة غير المتزامنة
  • أصبح عرض الخادم باستخدام Redux الآن بسيطًا للغاية ، فإليك دليل خطوة بخطوة مع Redux-First Router حول كيفية القيام بذلك كما لم تره من قبل: Server-Render مثل Pro / w Redux-First Router في 10 خطوات
  • أخيرًا ، للقيام بتقسيم الشفرة بشكل صحيح ، عليك أيضًا القيام بالأمرين (أي كلا SSR + تقسيم) . اتضح أن القيام بالأمرين في نفس الوقت كان نقطة ألم رئيسية ، وحققت بنجاح من قبل قلة ، ولم يكن لديك حتى الآن حزمة عامة لمساعدة المجتمع. React Universal Component + babel-plugin-universal-import + webpack-flush-chunksextract-css-chunks-webpack-plugin ) هي مجموعة من الحزم التي تحل هذه المشكلة حقًا. ولأول مرة. في الأساس ، يسمح لك بعرض المكونات بشكل متزامن على الخادم ، ولكن الأهم من ذلك هو نقل الأجزاء الدقيقة التي يتم تقديمها إلى العميل لتقديم متزامن أولي على العميل أيضًا. يمكنك أيضًا الحصول على أوراق أنماط css عبر المكون الإضافي webpack. هذا يختلف عما شاركهtimurtu والعديد من هذه المكونات ، والتي تتطلب تحميل main.js ، والتحليل ، والتقييم ، والعرض ، ثم أخيرًا بعد بضع ثوانٍ لطلب عمليات الاستيراد الديناميكية. هذه حلول لحل وميض المحتوى غير المصمم (FOUC) ، ولكن ليس لتضمين في صفحتك الأجزاء الدقيقة المعروضة على الخادم. Universal - اسم عائلتي من الحزم - يتيح لك القيام بذلك في وقت أسرع بكثير React Universal Component 2.0 & babel-plugin-universal-import

أعلم أنني لم أتناول إيجابيات / سلبيات مستوى المسار مقابل المكون ، لكن الرابط الأول يركز بشكل أساسي على ذلك. يتلخص الأمر بشكل أساسي في كون مستوى المكون سيئًا بالنسبة لـ SSR إذا كان لديك مكونات متداخلة يجب جلب بياناتها بالتسلسل (بدلاً من التوازي). وإذا كان لديك عملية جلب واحدة بشكل صحيح لكل مسار ، فمن الأفضل لك إضفاء الطابع الرسمي على العقد من خلال إرفاق تبعيات البيانات الخاصة بك بكيان مسار ، بدلاً من القيام بذلك في componentDidMount . توصل العديد من الآخرين أعلاه إلى نفس الاستنتاج. يقوم جهاز Redux-First Router بإضفاء الطابع الرسمي على هذا الأمر بشكل جيد للغاية على غرار نوع "العقود" التي تجعل العمل مع Redux ممتعًا للغاية.

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

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

يتمثل الاختلاف الأساسي بين RLR و RFR في أن RFR يرسل نوع إجراء مختلف لكل مسار (أي تغيير عنوان URL) ، بدلاً من إرساله دائمًا LOCATION_CHANGED . يتيح لك هذا التبديل بين تغييرات عناوين URL كأنواع فريدة في أدوات الاختزال ، تمامًا مثل أي إجراءات أخرى. قد يبدو صغيرا ، لكنه يحدث فرقا كبيرا. وبسبب ذلك ، فإنه لا يتطلب مكونات <Route /> ، وهو أمر غير ضروري في Redux land. هناك أيضًا قائمة غسيل ضخمة من الميزات التي يدعمها thunks إلى React Native و React Navigation وتقسيم الشفرة والجلب المسبق والمزيد.

أحب أن أسمع أفكار الناس.

faceyspacey شكرًا لك ، أعتقد أنه يعالج المشكلة التي كنت react-native-vector-icons كتعهد. إنها بالتأكيد طريقة مختلفة للنظر إلى الأشياء ولكنها تقلل من componentWillMount أو إعادة التشغيل X_GET_START و X_GET_END و X_GET_ERROR التي تربط المكونات غير المتزامنة بالحالة ، عندما تريد حقًا تقديم هذا الطلب مرة واحدة فقط لتقديم المكون. إذا كنت تقوم بأشياء مثل استطلاع البيانات ، فمن المحتمل أن يكون استخدام الحالة واستخدام إعادة التكثيف أكثر منطقية

faceyspacey أرى ما تقوله حول مستوى المسار ، لكن

أفضل؟ أين؟ على React Native؟ في المؤسسات الكبيرة مثل Facebook على تطبيقات React Native الخاصة بهم؟

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

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

أنا لست ضد مستوى المكون إذا لم يكن هناك SSR ولديك إستراتيجية الاختبار الخاصة بك بسلاسة وبعيدة عن الطريق. إذا كنت شركة عملاقة ، فمن المنطقي لأن كل مطور لا يحتاج إلى لمس مستوى المسار العلوي وربما كسره للآخرين. لهذا السبب كانت FB رائدة في هذا المسار مع Relay و GraphQL. حقيقة الأمر هي أن 100 شركة في العالم موجودة بالفعل في هذا القارب. لذلك أرى أن التشارك في الموقع هو ضجيج أكثر من الواقع لمعظم الأشخاص / التطبيقات / الشركات. بمجرد أن تتعطل شيئًا على مستوى المسار ويكون لديك حزمة تعمل بشكل جيد مثل Redux-First Router ، فسيكون لديك أسلوب أقل تشابكًا في تطوير نهج للفرق التي يُسمح لأعضائها

https://www.codesandbox.io

بمجرد أن ترى كيف يتم ذلك ، أود أن أسمع رأيك. ضع في اعتبارك أن هذا منتجع صحي. لذلك سيتعين عليك مراجعة الريبو التجريبي أو النموذج المعياري للحصول على مثال SSR. لكن هذه بداية جيدة.

أعتقد أن أسهل طريقة هي دعم طريقة التقديم غير المتزامن (يعود الوعد). سيسمح لمكون الجذر بانتظار عرض مكونات الأطفال وبالطبع ستكون نتيجة التقديم وعدًا. لقد نفذت شيئًا كهذا مسبقًا هنا https://github.com/3axap4eHko/preact-async-example

faceyspacey شكرًا لك على الإجابة المفصلة أعلاه. تعجبني حقًا فكرة Redux-First Router ، فهي تحل بالتأكيد جميع مشاكلي وتجعل الأشياء أكثر شفافية ونظافة مما كان لدينا من قبل.

شكرا جزيلا!

raRaRa سعيد لأنه أعجبك! ... أحد أكبر التحديات أنه لم يكن هناك تجريد جيد لجلب بيانات مستوى المسار حتى الآن. يحتوي React React v3 على عمليات رد نداء ، ولدى الإصدار v4 نمط ممتاز (لا سيما مع الحزمة react-router-config ) ، لكنه غير واضح وليس من الدرجة الأولى في الإصدار 4. إنها فكرة لاحقة. والأهم من ذلك ، أنه لا يعيش في Redux. لذلك ، هذه هي المرة الأولى التي يحصل فيها مستخدمو redux على تجريد كامل لـ "مستوى المسار".

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

ومع ذلك ، سيكون لدى RFR في النهاية تكامل على مستوى الطريق مع Apollo. هناك فوائد قليلة جدًا للقيام بالأشياء على مستوى المكونات ، باستثناء الاستثناءات النادرة المذكورة أعلاه. على الأقل 80٪ من الوقت (وربما 100٪ في تطبيقك) ، يمكنك تحديد جميع البيانات التي تحتاجها بناءً على المسار. إذا لم يكن ذلك ممكنًا ، فمن المحتمل أن يكون ذلك بسبب قيامك باستخلاص البيانات في "طبقة العرض" الخاصة بك والتي يمكن إعادة التفكير فيها جيدًا ليتم تفسيرها جميعًا بواسطة عنوان URL. لذا ، حتى باستخدام أدوات مثل Apollo ، تبدأ في الانخراط في أنماط مكافحة إشكالية والتي من المحتمل أن تسبب لك الألم في النهاية من خلال ترك "الحالة" تعيش في أي مكان آخر غير طبقة العرض. أي الحالة اللازمة لإجراء عمليات جلب البيانات هذه. غالبًا ما يتعين عليك تحسين المعلمات الدقيقة المستخدمة لجلب بياناتك. لذلك تأخذ الحالة والدعائم وتحول 2 للحصول على المعلمات قبل جلب البيانات. هذه هي الأشياء التي تعيش الآن في طبقة العرض وتخضع لآليات إعادة العرض الخاصة بها (أي عندما يتم استدعاء معالجات دورة الحياة). ينتهي كل تطبيق في وقت أو آخر بالبيانات التي لم يتم جلبها عندما يجب أن يتم جلبها أو يتم جلبها استجابةً للعناصر غير ذات الصلة التي تم استلامها / تغييرها. وفي جميع التطبيقات ، عليك كتابة كود إضافي للحماية من الدعائم غير ذات الصلة التي تغيرت. أي الدعائم التي لا تؤثر على المعلمات المستخدمة لجلب البيانات.

بالنسبة إلى React Native + Apollo ، فإن المشكلة أقل لأنك لا تمتلك SSR وبالتالي احتمالية حدوث عمليات جلب بيانات متسلسلة على الخادم. ومع ذلك ، هل تحتاج حقًا إلى جلب البيانات على مستوى المكون عندما تكون الشاشات صغيرة جدًا. أنت تعرف عمومًا ما يحتاجه كل "مشهد" من حيث بياناته. إنها ليست مثل لوحة تحكم لوحة الويب لسطح المكتب مع مليون رسم بياني ، وجداول متعددة ، وما إلى ذلك. ربما تكون حالة الاستخدام هذه هي أكبر مكان أساسي حيث يبدأ مستوى المكون في فهمه. ولكن حتى هناك يمكنك تحديد جميع متطلباتك لكل تلك الأدوات في مكان واحد وجلبها عبر Apollo. لم أفكر فيه بشكل كافٍ حتى الآن ، ولكن الفكرة الأساسية هي إرفاق متطلبات بيانات GraphQL الخاصة بك بمسار ، ثم في مكوناتك ، قم بالاتصال بالبيانات تمامًا مثل أي بيانات Redux أخرى. لذلك بشكل أكثر تحديدًا ، تكمن الفكرة في التخلص من وجود كل من رد الفعل - إعادة الإنتاج connect وما يعادله من Apollo. أنا فقط أريد واحدة ، ونريدها أن تكون أكثر تملقًا. يتطلب استخدام Apollo تدمير البيانات المتداخلة بشكل أعمق للوصول إلى ما تريده حقًا في مكوناتك. الرؤية هي إحدى الطرق التي تبدو تمامًا مثل Redux العادي ، بالإضافة إلى مواصفات الرسم البياني على مستوى المسار.

من السابق لأوانه التحدث عن ذلك ، لأنني بالكاد نظرت فيه ، ولكن إذا كان مستوى المسار هو النهج الصحيح لتطبيقك ، فلا ينبغي أن يكون Apollo + GraphQL استثناءً.

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

faceyspacey أوافق تماما. لكن يجب أن أعترف أنني لم أجرب Apollo أو GraphQL ، وسأفحصهما بالتأكيد وأرى كيف يتناسبان مع حالات الاستخدام الخاصة بي.

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

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

بالنسبة لي ، فإن Redux-First Router يشبه إلى حد كبير جزء وحدة التحكم في MVC ، بالإضافة إلى المسارات. وهو أمر منطقي جدا :)

شكرا لك.

في نهاية اليوم ، مجموعتنا الجديدة هي:

م: إحياء
الخامس: رد فعل
C: Redux-First Router (ستتم إعادة تسميته قريبًا إلى "Rudy" )

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

قد تعمل بشكل مختلف قليلاً في المكدس الجديد للعميل أولاً مقابل MVC التقليدي من جانب الخادم ، ولكنه في الأساس نفس الفصل الثالث للمخاوف.

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

مرحبا شباب ، شاهد هذا الرابط. هنا مثال عرض جانب خادم البيانات https://github.com/bananaoomarang/isomorphic-redux

@ harut55555 أتساءل ، قد يكون هذا أنا فقط ولكن هذا يبدو وكأنه الكثير من التعليمات البرمجية للقيام بطلب الحصول على طلب ونشر

أية تغييرات؟ صدر 16 رد فعل ومعظم الحلول لا تعمل

أعتقد أن النهج الحالي هو استخدام redux مع أدوات مثل redux قابل للملاحظة أو redux thunk

حالة الاستخدام الخاصة بي

<App>
    <Page>
        <AsyncModule hre="different.com/Button.react.js" /> downloaded from external url on server or client
    </Page>
</App>

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

لماذا لا تقوم بتنزيل البيانات / المحتوى بدلاً من المكون فقط للفضول؟

متي؟ لدي صفحات ديناميكية والمكون قد يكون أو لا يكون

يبدو أنك تريد العرض الشرطي https://reactjs.org/docs/conditional-rendering.html

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

إن استخدام @graphql من Apollo يجعل تحميل البيانات أمرًا بسيطًا للغاية ، كما أن واجهة برمجة التطبيقات القائمة على المكون React-Router v4 تجعل التوجيه سهل التركيب. كلاهما متعامد مع حالة التطبيق في Redux.

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

ثم @graphql يمكنه ببساطة إرجاع الوعد بالتصيير () بعد تحميل البيانات ؛ كل ما تبقى هو مجرد رد فعل عادي.

قبل بضعة أشهر ، ألقيت حديثًا في JSConf Iceland الذي يصف ميزات العرض غير المتزامن القادمة في React (انظر الجزء الثاني): https://reactjs.org/blog/2018/03/01/sneak-peek-beyond-react -16.html. يتعلق هذا بجلب البيانات من جانب العميل.

الآن ألقى acdlite حديثًا حول كيفية تطبيق نفس المفاهيم لتمكين انتظار البيانات بشكل غير متزامن على الخادم في مكونات https://www.youtube.com/watch؟ z-6JC0_cOns

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

أتذكر الخاتم. نحن نتزوج التخطيط لمستقبل معا. من فضلك أنهي هذا الآن وتعال لرؤيتي. يعمل الوقت دائما الحب

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

لقد اتخذت هذا الأسلوب في react-baconjs : render-to-html.js . لقد استوحى هذا التعليق من تعليق gaearon في عدد آخر يوصي بمثل هذا النهج.

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

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

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

تضمين التغريدة لقد فكرت في تعميم حل SSR غير المتزامن المحدد. هل يتعامل رد الفعل الأمامي مع عمق غير متزامن غير محدود؟ يسأل لأنك قلت "مرتين".

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

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

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

لمعلوماتك ، بدأنا العمل على هذا.

https://reactjs.org/blog/2018/11/27/react-16-roadmap.html#suspense -for-server-rendering

رهيبة giron!

davnicwil react-baconjs يدعم العمق غير المحدود.

gaearon أتساءل عما إذا كان هذا سيجعل الدعم ممكنًا

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

يدعم @ steve-taylor reaction-frontload الآن أيضًا عمق غير محدود لتداخل المكونات ، مع إصدار 1.0.7 .

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

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

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

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