javascript - ماهو - react ترجمة




كيفية تمرير الدعائم إلى{this.props.children} (13)

السيناريو 1 - تمرير الدعائم لتوجيه الأطفال.

انظر جميع الإجابات الأخرى

السيناريو الثاني - تمرير البيانات / التبعيات من خلال شجرة المكونات عبر context

تابع القراءة.

context React يجعل البيانات متاحة / تمكن حقن التبعية لجميع الأطفال ومكونات subcildren ، وهنا مثال على ذلك

class Child extends React.Component {
  render() {
    return (
      <div onClick={() => this.context.doSomething(this.props.value)}>
        Click Me
      </div>
    );
  }
};


// Access parent context by defining contextTypes
Child.contextTypes = {
  doSomething: React.PropTypes.func
};

class Parent extends React.Component {
  // passes the information down to its children
  getChildContext() {
    return { doSomething : this.doSomething };
  }

  doSomething(value) {
    console.log('doSomething called by child with value:', value);
  },

  render() {
    return <div>{this.props.children}</div>
  }
};

// make information available to its children
Parent.childContextTypes = {
  doSomething: React.PropTypes.func
};

ReactDOM.render(
  <Parent>
    <Child value="1" />
    <Child value="2" />
  </Parent>,
  document.getElementById('container')
);

This المادة.

إخلاء المسؤولية: تشير وثائق React إلى أن context هو واجهة برمجة تطبيقات تجريبية ، ولكنه لم يتغير لسنوات حتى الآن. أيضا ، هناك حاجة في الواقع في بعض الحالات ، وهذا هو السبب في واحدة من أشهر مكتبات React التي تستفيد منها داخليا - React Router . إذا كنت ترغب في الذهاب إلى جانب السوبر آمنة ، قد ترغب في context مجردة بطريقة تناسب احتياجاتك.

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

<Parent>
  <Child value="1">
  <Child value="2">
</Parent>

هناك منطق يجري لتقديمه بين مكونات الوالدين والأطفال بالطبع ، يمكنك تخيل <select> و <option> كمثال لهذا المنطق.

هذا هو تنفيذ وهمي لغرض السؤال:

var Parent = React.createClass({
  doSomething: function(value) {
  },
  render: function() {
    return (<div>{this.props.children}</div>);
  }
});

var Child = React.createClass({
  onClick: function() {
    this.props.doSomething(this.props.value); // doSomething is undefined
  },
  render: function() {
    return (<div onClick={this.onClick}></div>);
  }
});

السؤال المطروح هو عندما تستخدم {this.props.children} لتعريف مكون المجمع ، كيف {this.props.children} بعض الممتلكات إلى جميع أطفالها؟


Parent.jsx:

import React from 'react';

const doSomething = value => {};

const Parent = props => (
  <div>
    {
      !props || !props.children 
        ? <div>Loading... (required at least one child)</div>
        : !props.children.length 
            ? <props.children.type {...props.children.props} doSomething={doSomething} {...props}>{props.children}</props.children.type>
            : props.children.map((child, key) => 
              React.cloneElement(child, {...props, key, doSomething}))
    }
  </div>
);

Child.jsx:

import React from 'react';

/* but better import doSomething right here,
   or use some flux store (for example redux library) */
export default ({ doSomething, value }) => (
  <div onClick={() => doSomething(value)}/>
);

و main.jsx:

import React from 'react';
import { render } from 'react-dom';
import Parent from './Parent';
import Child from './Child';

render(
  <Parent>
    <Child/>
    <Child value='1'/>
    <Child value='2'/>
  </Parent>,
  document.getElementById('...')
);

انظر المثال هنا: https://plnkr.co/edit/jJHQECrKRrtKlKYRpIWl?p=preview


إذا كان لديك العديد من الأطفال الذين ترغب في تمريرهم إلى الدعائم ، فيمكنك فعل ذلك بهذه الطريقة باستخدام React.Children.map:

render() {
    let updatedChildren = React.Children.map(this.props.children,
        (child) => {
            return React.cloneElement(child, { newProp: newProp });
        });

    return (
        <div>
            { updatedChildren }
        </div>
    );
}

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

render() {
    return (
        <div>
            {
                React.cloneElement(this.props.children, {
                    newProp: newProp
                })
            }
        </div>
    );
}

بالإضافة إلى الإجابة علىand_rest ، هذه هي الطريقة التي استنسخ بها الأطفال وأضيف صفًا.

<div className="parent">
    {React.Children.map(this.props.children, child => React.cloneElement(child, {className:'child'}))}
</div>

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

وظيفة كمكونات الطفل


طريقة نظافة النظر في واحد أو أكثر من الأطفال

<div>
   { React.Children.map(this.props.children, child => React.cloneElement(child, {...this.props}))}
</div>

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

var Parent = React.createClass({
doSomething: function() {
    console.log('doSomething!');
},

render: function() {
    var that = this;
    var childrenWithProps = React.Children.map(this.props.children, function(child) {
        return React.cloneElement(child, { doSomething: that.doSomething });
    });

    return <div>{childrenWithProps}</div>
}})

تحديث: هذا الإصلاح لـ ECMAScript 5 ، في ES6 ليس هناك حاجة في var that = this


لا أحد من الإجابات يعالج مسألة إنجاب أطفال ليسوا مكونات React React ، مثل سلاسل النص. يمكن أن يكون الحل البديل شيئًا كالتالي:

// Render method of Parent component
render(){
    let props = {
        setAlert : () => {alert("It works")}
    };
    let childrenWithProps = React.Children.map( this.props.children, function(child) {
        if (React.isValidElement(child)){
            return React.cloneElement(child, props);
        }
          return child;
      });
    return <div>{childrenWithProps}</div>

}

لم يكن سبب React.children يعمل بالنسبة لي. هذا ما نجح بالنسبة لي.

أردت فقط إضافة فصل إلى الطفل. على غرار تغيير الدعامة

 var newChildren = this.props.children.map((child) => {
 const className = "MenuTooltip-item " + child.props.className;
    return React.cloneElement(child, { className });
 });

 return <div>{newChildren}</div>;

الخدعة هنا هي React.cloneElement . يمكنك تمرير أي دعم بطريقة مماثلة


مع التحديث إلى React 16.3 ، يمكنك الآن استخدام React.createContext .

import * as React from 'react';

// React.createContext accepts a defaultValue as the first param
const { ParentProvider, ChildConsumer } = React.createContext(); 

class Parent extends React.Component {
  doSomething = (value) => {
    // Do something here with value
  };

  render() {
    return (
       <ParentProvider value={{ onClick: this.doSomething }}>
         {this.props.children}
       </ParentProvider>
    );
  }
}

class Child extends React.Component {
  render() {
    const { value } = this.props;
    return (
       <ChildConsumer> 
         (({ doSomething }) => {
           return <div onClick={() => doSomething(value)}>{value}</div>
         })
       </ChildConsumer>
    );
  }
}


// Example of using Parent and Child

import * as React from 'react';

class SomeComponent extends React.Component {

  render() {
    <Parent>
      <Child value={1} />
      <Child value={2} />
    </Parent>
  }
}

يضيء React.createContext حيث يتعذر معالجة حالة React.cloneElement المكونات المتداخلة

class SomeComponent extends React.Component {

  render() {
    <Parent>
      <Child value={1} />
      <SomeOtherComp><Child value={2} /></SomeOtherComp>
    </Parent>
  }
}

وفقا لوثائق cloneElement()

React.cloneElement(
  element,
  [props],
  [...children]
)

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

React.cloneElement() يكافئ تقريباً:

<element.type {...element.props} {...props}>{children}</element.type>

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

لذا ، فإن cloneElement هي ما ستستخدمه لتوفير الدعائم المخصصة للأطفال. ومع ذلك ، يمكن أن يكون هناك العديد من الأطفال في المكون ، وسوف تحتاج إلى تكرار حلقة فوقها. ما هي الإجابات الأخرى التي تقترح عليك أن تقوم React.Children.map باستخدام React.Children.map . ومع ذلك ، فإن React.Children.map على عكس React.cloneElement يغير مفاتيح عنصر React.Children.map React.cloneElement .$ كبادئة. تحقق من هذا السؤال لمزيد من التفاصيل: React.cloneElement داخل React.Children.map يتسبب في تغيير عناصر العناصر

إذا كنت ترغب في تجنب ذلك ، يجب أن تذهب بدلا من ذلك لوظيفة forEach مثل

render() {
    const newElements = [];
    React.Children.forEach(this.props.children, 
              child => newElements.push(
                 React.cloneElement(
                   child, 
                   {...this.props, ...customProps}
                )
              )
    )
    return (
        <div>{newElements}</div>
    )

}

يمكن ببساطة أن يتم مثل:

interface PaginationItemProps extends React.HTMLProps<HTMLDivElement> {
}

const PaginationItem = (props: PaginationItemProps) => {
   return <div>{props.children}</div>;
}

class Pagination extends React.Component<PaginationProps> {
  render() {
    return <div>          
        <PaginationItem>CHILDREN RENDER</PaginationItem>
    </div>
 }
}

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

<div>{React.cloneElement(this.props.children, {...this.props})}</div>

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

في React v0.13 RC2 سنقدم واجهة برمجة تطبيقات جديدة ، مشابهة لـ React.addons.cloneWithProps ، مع هذا التوقيع:

React.cloneElement(element, props, ...children);

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

يكافئ React.cloneElement تقريبًا:

<element.type {...element.props} {...props}>{children}</element.type>

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

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

var newChildren = React.Children.map(this.props.children, function(child) {
  return React.cloneElement(child, { foo: true })
});

ملاحظة: React.cloneElement (child، {ref: 'newRef'}) لا تتخطى المرجع ، لذلك لا يزال من غير الممكن أن يكون لوالدين حق الرجوع إلى نفس الطفل ، ما لم تستخدم رد الاتصال.

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

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

المزيد here ...





react-jsx