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

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

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

ما هو السلوك الحالي؟

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

import React from 'react';
import {render} from 'react-dom';

const { Provider, Consumer} = React.createContext();

const Comp = ({children})=> <Provider>{cloneKids(children)}</Provider>;

const cloneKids=(children)=>React.Children.map(children, child =>
                           React.cloneElement(child, child.props,
                                  child.props.children&&
                                  cloneKids(child.props.children)));
render(
    <Comp><Consumer>{console.log}</Consumer></Comp>,
    document.getElementById('root')
);

ينتج الرمز التحذير والخطأ المقدم مع # 12241

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

و (أكثر إرباكًا)

TypeError: التصيير ليس دالة

ما هو السلوك المتوقع؟

ربما يجب ألا يحاول React.cloneElement استنساخ الوظائف؟ مهما كان الأمر ، فإن النتيجة ليست دالة.

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

ما إصدارات React وأي متصفح / نظام تشغيل متأثر بهذه المشكلة؟

تم الاختبار مع التفاعل 16.3.0 في Stackblitz / Chrome 65 والتفاعل مع 16.3.2 في Chrome 65 و Firefox 59

Question

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

المشكلة ليست مع cloneElement (ليس لها منطق خاص للسياق) ، لكنك تقوم بتمرير props.children (وهي وظيفة في هذه الحالة) إلى Children.map() (التي لا تتوقع وظائف). Children.map يعمل فقط مع عقد React العادية.

ربما يعرض Children.map تحذيرًا عندما يواجه شيئًا ليس عقدة React.

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

ال 4 كومينتر

المشكلة ليست مع cloneElement (ليس لها منطق خاص للسياق) ، لكنك تقوم بتمرير props.children (وهي وظيفة في هذه الحالة) إلى Children.map() (التي لا تتوقع وظائف). Children.map يعمل فقط مع عقد React العادية.

ربما يعرض Children.map تحذيرًا عندما يواجه شيئًا ليس عقدة React.

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

شكرا!

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

<Parent ><Child prefix-prop="string expression"></Parent>
(لغة ​​التعبير ليست جافا سكريبت ويتم تقييمها عن بعد. أنا لا أتحكم في الطفل ، ويمكن أن يكون هناك أي عدد من الأطفال).

يصبح الطفل داخليًا شيئًا مثل:

<Child prop={evaluate("string expression")} />

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

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

<Parent>{ context=> <Child prop={context.evaluate(x)} />}</Parent>

(بالإضافة إلى ذلك ، إذا نسوا مسافة قبل الوظيفة مباشرة ، فسيتم الخلط بينهم # 12689)

ولن يفهموا بسرعة هذا النموذج أيضًا:
<Parent display={ context=> <Child prop={context.evaluate(x)} />} />

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

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

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

فكرة أخرى ألعب معها هي والد وظيفي ، ربما يعيد المكون (نوع من المكوّن الإضافي)

({context})=>
context.parent("context expression",
     context2=><Child prop={context2.evaluate("sub-expression")} context={context2} />)

حيث يمكن للطفل أن يحتوي مرة أخرى على استدعاءات Context.parent () وما إلى ذلك.

بالطبع يمكن للوالد () استخدام سياق المستهلك في التصيير () للمكون الذي يعيده ، لذلك يمكن إسقاط خاصية السياق:

()=>
parent("context expression",
     context2=><Child prop={context2.evaluate("sub-expression")} />)

_المشكلة هنا أن الأصل () كونه مكونًا يمكنه الوصول إلى سياق React ، لكن التقييم () لا يمكنه (على حد علمي) الوصول إلى سياق React ما لم يُرجع مكونًا_

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

لذلك أعتقد أن الوصول إلى سياق React من المكونات الخارجية سيكون مثاليًا. شيء مثل

React.getContext(Consumer, data=> ...)

إذا كنت أتذكر جيدًا ، عندما كنت أعاني من ذلك ، حاولت استدعاء Consumer.render () يدويًا باستخدام إطار عمل الاختبار ، لكنني لم أحصل على أي شيء ذي معنى.

ملاحظة: قد يبدو الرمز الأول أعلاه غامضًا ولكنه في الواقع مألوف تمامًا مع نموذج JSP الحالي لذا أعتقد أنه يمكنني بيعه للمستخدمين :)

<context:parent ctx="context-expression">
   HTML...<context:evaluate expr="sub-expression" />...HTML
</context:parent>

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

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