কীভাবে প্রপসগুলি pass this.prop.children pass এ পাস করবেন


887

আমি কিছু উপাদানকে জেনেরিক উপায়ে ব্যবহার করা যেতে পারে তার সংজ্ঞা দেওয়ার সঠিক উপায়টি খুঁজতে চেষ্টা করছি:

<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}একটি মোড়কের উপাদান সংজ্ঞায়িত করতে ব্যবহার করেন আপনি কীভাবে তার সমস্ত শিশুদের কিছু সম্পত্তি দেবেন?


উত্তর:


955

নতুন প্রপস দিয়ে বাচ্চাদের ক্লোনিং করা

বাচ্চাদের উপর পুনরাবৃত্তি করতে আপনি React.Children ব্যবহার করতে পারেন এবং তারপরে React.cloneElement ব্যবহার করে প্রতিটি উপাদানকে নতুন প্রপস (অগভীর মার্জড) দিয়ে ক্লোন করতে পারেন :

import React, { Children, isValidElement, cloneElement } from 'react';

const Child = ({ doSomething, value }) => (
  <div onClick={() => doSomething(value)}>Click Me</div>
);

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

  render() {
    const childrenWithProps = Children.map(children, child => {
      // Checking isValidElement is the safe way and avoids a TS error too.
      if (isValidElement(child)) {
        return cloneElement(child, { doSomething })
      }

      return child;
    });

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

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

ফিডল: https://jsfiddle.net/2q294y43/2/

বাচ্চাদের একটি ফাংশন হিসাবে ডাকা হচ্ছে

প্রপস রেন্ডার সহ আপনি বাচ্চাদের প্রপসও দিতে পারেন । এই পদ্ধতির মধ্যে বাচ্চারা (যা childrenবা অন্য কোনও প্রপ নাম হতে পারে ) এমন একটি ফাংশন যা আপনি পাস করতে চান এমন কোনও যুক্তি মেনে নিতে এবং বাচ্চাদের ফিরিয়ে দিতে পারেন:

const Child = ({ doSomething, value }) => (
  <div onClick={() =>  doSomething(value)}>Click Me</div>
);

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

  render() {
    // Note that children is called as a function and we can pass args to it
    return <div>{children(doSomething)}</div>
  }
};

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

আপনি যদি পছন্দ করেন তবে এর পরিবর্তে <React.Fragment>বা কেবল <>আপনি কোনও অ্যারেও ফিরিয়ে দিতে পারেন।

ফিডল: https://jsfiddle.net/ferahl/y5pcua68/7/


7
এটি আমার পক্ষে কাজ করে না। এটি React.cloneElement ()
প্যাট্রিক

12
এই উত্তরটি কাজ করে না, valueপাস করা doSomethingহারিয়ে গেছে।
ডেভ

3
@ ডোমিনিকটোবিয়াস আরগ, দুঃখিত, আমি সতর্ক হতে কনসোল.লগ পরিবর্তন করেছিলাম এবং দুটি প্যারামকে একক স্ট্রিংয়ে একত্রে ভুলে যেতে ভুলে গেছি।
ডেভ

1
এই উত্তরটি অত্যন্ত সহায়ক ছিল, তবে আমি এখানে এমন একটি ইস্যুতে ছড়িয়ে পড়েছি যা এখানে উল্লেখ করা হয়নি এবং আমি ভাবছিলাম যে এটি কোনও নতুন জিনিস যা পরিবর্তিত হয়েছে বা এটি আমার শেষের মতো কিছু অদ্ভুত কিনা। আমি যখন আমার সন্তানের উপাদানটিকে ক্লোন করেছি তখন আমি ক্লোনএলিমেন্টের তৃতীয় যুক্তিতে এই.প্রপ.সিল্ডার.প্রোপস.চিল্ড্রেন যুক্ত না হওয়া অবধি শিশুটিকে পুরানো উপাদানটিতে সেট করা হয়েছিল।
এফেনিন

7
যদি শিশুটি কোনও রুটের (v4) মাধ্যমে আলাদা রুটের পৃষ্ঠা থেকে লোড করা হয় তবে কী হবে?
blamb

393

এটি করার জন্য কিছুটা পরিষ্কার পদ্ধতির জন্য চেষ্টা করুন:

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

সম্পাদনা করুন: একাধিক স্বতন্ত্র বাচ্চাদের সাথে ব্যবহার করতে (সন্তানের নিজেরাই একটি উপাদান হতে হবে) আপনি করতে পারেন। 16.8.6 এ পরীক্ষা করা হয়েছে

<div>
    {React.cloneElement(props.children[0], { loggedIn: true, testingTwo: true })}
    {React.cloneElement(props.children[1], { loggedIn: true, testProp: false })}
</div>

10
আমি সর্বাধিক রেট করা উত্তরটি ব্যবহার করছিলাম, তবে এইটি আরও অনেক সোজা এগিয়ে! এই সমাধানটি তারা প্রতিক্রিয়া-রাউটার উদাহরণ পৃষ্ঠায় কী ব্যবহার করে।
ক্যাপডডাইলাইট

10
কেউ কীভাবে এটি ব্যাখ্যা করতে পারে (বা এটি আসলে কী করে)? পড়া ডক্স , আমি দেখতে পাইনি কিভাবে এই শিশুদের মধ্যে নামা এবং প্রতিটি সন্তানের যে ঠেকনা যোগ হবে - কি এটা করতে দেয়ার উদ্দেশ্যে করা হচ্ছে হল? যদি এটি হয়, তবে আমরা কীভাবে জানব যে এটি এটিই করবে? এটি একেবারেই সুস্পষ্ট নয় যে এটি একটি অস্বচ্ছ ডেটা স্ট্রাকচার ( this.props.children) থেকে cloneElement... যা কোনও উপাদান উপাদান প্রত্যাশা করে তা পাস করা বৈধও নয় ।
গ্রিনআসজেড

51
হুবহু, এটি একাধিক বাচ্চাদের সাথে কাজ করবে বলে মনে হচ্ছে না।
দানিতা 12

17
সুতরাং আপনি এমন কোডটি লিখতে পারেন যা কাজ করে যখন কেউ কেবলমাত্র একটি শিশুকে একটি উপাদান হিসাবে প্রবেশ করে, কিন্তু যখন তারা অন্য যুক্ত করে, এটি ক্র্যাশ হয়ে যায় ... যা মুখের মানটিতে দুর্দান্ত শোনাচ্ছে না? এটি ওপির জন্য একটি ফাঁদ বলে মনে হবে, যিনি সমস্ত শিশুদের প্রপস পাস করার বিষয়ে বিশেষভাবে জিজ্ঞাসা করেছিলেন ।
গ্রিনআসজেড 5'16

10
@ গ্রীনআসজেড যতক্ষণ না আপনার উপাদানটি একক সন্তানের প্রত্যাশা করে থাকে ঠিক আছে। আপনি আপনার উপাদানগুলির প্রোপাইপগুলির মাধ্যমে এটি নির্ধারণ করতে পারেন যে এটি একক সন্তানের প্রত্যাশা করে। React.Children.onlyফাংশন একমাত্র শিশুকে ফিরিয়ে দেয় বা একাধিক থাকলে ব্যতিক্রম ছুঁড়ে ফেলে (যদি ব্যবহারের কেস না থাকে তবে এটি উপস্থিত হত না)।
চেম্বারলাইন

80

এটা চেষ্টা কর

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

এটি প্রতিক্রিয়া -15.1 ব্যবহার করে আমার জন্য কাজ করেছে।


3
ট্যাগগুলির React.cloneElement()চারপাশে না ঘুরে সরাসরি ফিরে আসা কি সম্ভব <div>? কারণ যদি শিশুটি একটি <span>(বা অন্য কিছু) হয় এবং আমরা এর ট্যাগ উপাদান টাইপটি সংরক্ষণ করতে চাই?
adrianmc

1
যদি এটি একটি শিশু হয় তবে আপনি মোড়কটি ছেড়ে দিতে পারেন এবং এই সমাধানটি কেবলমাত্র একটি সন্তানের পক্ষে কাজ করে তাই হ্যাঁ।
থজায়

1
আমার জন্য কাজ কর. <ডিভ> সংযুক্ত না করে ঠিক আছে।
ক্র্যাশ ওভাররাইড

4
যদি আপনার স্পষ্টভাবে প্রয়োগ করা দরকার যে আপনি কেবল একটি শিশু পেয়েছেন, আপনি এটি করতে পারেন React.cloneElement(React.Children.only(this.props.children), {...this.props})যা এটির চেয়ে বেশি সন্তানের পাস হলে এটি একটি ত্রুটি ছুঁড়ে ফেলবে। তারপরে আপনার কোনও ডিভের মধ্যে মোড়ানো দরকার নেই।
itananderson

1
এই উত্তরটি একটি টাইপরর তৈরি করতে পারে: চক্রাকার বস্তুর মান। আপনি যদি না চান বাচ্চার প্রপসগুলির মধ্যে একটি নিজে হয়, তবে ব্যবহার করুন let {children, ...acyclicalProps} = this.propsএবং তারপরে React.cloneElement(React.Children.only(children), acyclicalProps)
প্যারাবোলর্ড

68

সরাসরি বাচ্চাদের প্রপস পাস।

অন্যান্য সমস্ত উত্তর দেখুন

প্রসঙ্গের মাধ্যমে উপাদান গাছের মাধ্যমে ভাগ করা, বৈশ্বিক ডেটা পাস করুন Pass

প্রসঙ্গটি এমন ডেটা ভাগ করে নেওয়ার জন্য ডিজাইন করা হয়েছে যা প্রতিক্রিয়া উপাদানগুলির একটি গাছের জন্য "বৈশ্বিক" হিসাবে বিবেচিত হতে পারে, যেমন বর্তমান প্রমাণীকৃত ব্যবহারকারী, থিম, বা পছন্দসই ভাষা। 1

দাবি অস্বীকার: এটি একটি আপডেট করা উত্তর, পূর্ববর্তীটি পুরানো প্রসঙ্গের এপিআই ব্যবহার করেছিল

এটি গ্রাহক / সরবরাহ নীতির উপর ভিত্তি করে। প্রথমে আপনার প্রসঙ্গ তৈরি করুন

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

তারপরে ব্যবহার করুন

<Provider value={/* some value */}>
  {children} /* potential consumers */
<Provider />

এবং

<Consumer>
  {value => /* render something based on the context value */}
</Consumer>

সরবরাহকারীর বংশধর সমস্ত গ্রাহক যখনই সরবরাহকারীর মান উত্স পরিবর্তন হবে তখন পুনরায় রেন্ডার করবে। সরবরাহকারীর থেকে তার বংশধর গ্রাহকগণের কাছে প্রচারটি কাঁপোমেনডআপডেট পদ্ধতির সাপেক্ষে নয়, সুতরাং পূর্বপুরুষের উপাদানটি আপডেটের বাইরে চলে গেলেও গ্রাহক আপডেট হয়। 1

সম্পূর্ণ উদাহরণ, আধা সিউডো কোড।

import React from 'react';

const { Provider, Consumer } = React.createContext({ color: 'white' });

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: { color: 'black' },
    };
  }

  render() {
    return (
      <Provider value={this.state.value}>
        <Toolbar />
      </Provider>
    );
  }
}

class Toolbar extends React.Component {
  render() {
    return ( 
      <div>
        <p> Consumer can be arbitrary levels deep </p>
        <Consumer> 
          {value => <p> The toolbar will be in color {value.color} </p>}
        </Consumer>
      </div>
    );
  }
}

1 https://facebook.github.io/react/docs/context.html


6
গৃহীত উত্তরের মতো নয় এটি প্যারেন্টের অধীনে অন্তর্ভুক্ত অন্যান্য উপাদান থাকা অবস্থায়ও সঠিকভাবে কাজ করবে। এটি অবশ্যই সেরা উত্তর।
জ্যাপ্ট্রি

6
প্রপস! = প্রসঙ্গ
পেট্র পেলার

আপনি প্রসঙ্গে প্রচারের পরিবর্তনের উপর নির্ভর করতে পারবেন না। প্রপস যখন এটি সম্ভব তখন ব্যবহার করুন।
থজায়

1
হয়তো আমি বুঝতে পারছি না তবে "প্রসঙ্গ প্রপসগুলি উপলব্ধ করে" বললে কি ভুল হয় না? আমি যখন সর্বশেষ প্রসঙ্গটি ব্যবহার করেছি, তখন এটি একটি পৃথক জিনিস ছিল (অর্থাত্ this.context) - এটি যাদুকরভাবে প্রসঙ্গগুলি প্রপসের সাথে একীভূত করে নি। আপনাকে ইচ্ছাকৃতভাবে প্রসঙ্গটি সেট এবং ব্যবহার করতে হয়েছিল, যা সম্পূর্ণ অন্য জিনিস।
জোশ

আপনি পুরোপুরি বুঝতে পারেন, এটি ভুল ছিল। আমি আমার উত্তর সম্পাদনা করেছি।
লিউবুমির

48

নেস্টেড বাচ্চাদের কাছে প্রপস পাস করা

আপডেটে সঙ্গে প্রতিক্রিয়া 16.6 আপনি এখন ব্যবহার করতে পারেন React.createContext এবং contextType

import * as React from 'react';

// React.createContext accepts a defaultValue as the first param
const MyContext = React.createContext(); 

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

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

class Child extends React.Component {
  static contextType = MyContext;

  onClick = () => {
    this.context.doSomething(this.props.value);
  };      

  render() {
    return (
      <div onClick={this.onClick}>{this.props.value}</div>
    );
  }
}


// Example of using Parent and Child

import * as React from 'react';

class SomeComponent extends React.Component {

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

React.createContext উজ্জ্বল হয় যেখানে React.cloneElement কেস নেস্টেড উপাদানগুলি পরিচালনা করতে পারে না

class SomeComponent extends React.Component {

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

3
=> ফাংশনগুলি একটি খারাপ অভ্যাস কেন তা ব্যাখ্যা করতে পারেন? => ফাংশন ইভেন্ট হ্যান্ডলারদের thisপ্রসঙ্গ পেতে বাঁধতে সহায়তা করে
কেনেথ ট্রুং

@ কেনেথট্রুং কারণ প্রতিবার এটি রেন্ডার করে একটি ফাংশন তৈরি করে।
itdoesntwork

9
@itdoesntwork এটি সত্য নয়। ক্লাসটি তৈরি করা হলে এটি কেবল একটি নতুন ফাংশন তৈরি করে। এটি রেন্ডার ফাংশন চলাকালীন তৈরি হচ্ছে না ..
কেনেথ ট্রুং

@ কেনেথট্রুং রিঅ্যাক্টজস.আর্গ / ডকস / ফাফ- ফাংশনস html # arrow-function-in- reender আমি ভেবেছিলাম আপনি রেন্ডারে তীর ফাংশন সম্পর্কে কথা বলছেন।
itdoesntwork

24

আপনি ব্যবহার করতে পারেন React.cloneElement, আপনার অ্যাপ্লিকেশনটিতে এটি ব্যবহার শুরু করার আগে এটি কীভাবে কাজ করে তা আরও ভাল। এটি চালু করা হয়েছে React v0.13, আরও তথ্যের জন্য পড়ুন, তাই আপনার জন্য এই কাজের পাশাপাশি কিছু:

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

এটি কীভাবে কাজ করছে এবং কীভাবে আপনি সেগুলি ব্যবহার করতে পারেন তা বোঝার জন্য আপনার জন্য প্রতিক্রিয়ার ডকুমেন্টেশন থেকে লাইনগুলি আনুন:

প্রতিক্রিয়া v0.13 আরসি 2 এ আমরা এই স্বাক্ষর সহ React.addons.cloneWithProp এর অনুরূপ একটি নতুন এপিআই প্রবর্তন করব:

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

ক্লোনওথপথগুলির বিপরীতে, এই নতুন ফাংশনটিতে কোনও যাদু অন্তর্নির্মিত আচরণ নেই শৈলী এবং শ্রেণিকামের জন্য মার্জ করার জন্য একই কারণে আমাদের কাছে ট্রান্সফারপ্রোসটো থেকে সেই বৈশিষ্ট্য নেই। ম্যাজিক জিনিসের সম্পূর্ণ তালিকা আসলে কী, তা কেউ নিশ্চিত নয়, যা শৈলীর আলাদা স্বাক্ষর রয়েছে (যেমন আসন্ন প্রতিক্রিয়াশীল নেটিভ) তে যখন কোডটির বিষয়ে যুক্তি দেখাতে অসুবিধা এবং পুনরায় ব্যবহার করা কঠিন করে তোলে।

React.cloneElement প্রায় সমতুল্য:

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

তবে, জেএসএক্স এবং ক্লোনওয়াইথপ্রপসের বিপরীতে এটি রেফগুলি সংরক্ষণ করে। এর অর্থ হ'ল আপনি যদি কোনও সন্তানের সাথে এটির উপর নির্ভর করে পান তবে আপনি দুর্ঘটনাক্রমে আপনার পূর্বপুরুষের কাছ থেকে এটি চুরি করবেন না। আপনি আপনার নতুন উপাদানের সাথে একই রেফ সংযুক্ত পাবেন।

একটি সাধারণ প্যাটার্ন হ'ল আপনার বাচ্চাদের উপরে মানচিত্র তৈরি করা এবং একটি নতুন প্রপ যোগ করা। ক্লোনওয়েথপ্রপসগুলি রেফ হারিয়েছে এমন বিষয়ে অনেকগুলি প্রতিবেদন করা হয়েছে, এটি আপনার কোড সম্পর্কে যুক্তিযুক্ত হতে শক্ত করে তোলে। এখন ক্লোন এলিমেন্ট সহ একই ধাঁচ অনুসরণ করা প্রত্যাশা অনুযায়ী কাজ করবে। উদাহরণ স্বরূপ:

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

দ্রষ্টব্য: React.cloneElement (শিশু, {রেফ: 'newRef'}) রেফটিকে ওভাররাইড করে তোলে তাই যদি আপনি কলব্যাক-রেফ ব্যবহার না করেন তবে দুটি পিতা-মাতার পক্ষে একই সন্তানের রেফ দেওয়া সম্ভব নয়।

প্রসগুলি এখন অপরিবর্তনীয় হওয়ায় এটি 0.13 প্রতিক্রিয়াতে প্রবেশ করার জন্য একটি সমালোচনামূলক বৈশিষ্ট্য ছিল। আপগ্রেডের পথটি প্রায়শই উপাদানটির ক্লোন করতে হয় তবে এটি করে আপনি রেফটি হারাতে পারেন। অতএব, আমাদের এখানে একটি ভাল আপগ্রেড পথ প্রয়োজন। আমরা যখন ফেসবুকে কলসাইটগুলি আপগ্রেড করছিলাম তখন আমরা বুঝতে পারি যে আমাদের এই পদ্ধতির দরকার। আমরা সম্প্রদায় থেকে একই প্রতিক্রিয়া পেয়েছি। অতএব আমরা চূড়ান্ত রিলিজের আগে অন্য আরসি করার সিদ্ধান্ত নিয়েছি যাতে এটি নিশ্চিত হয়ে যায়।

আমরা অবশেষে রিঅ্যাক্ট.এডডনস.ক্লোনওথপ্রপগুলি হ্রাস করার পরিকল্পনা করি plan আমরা এটি এখনও করছি না, তবে এটি আপনার নিজের ব্যবহার সম্পর্কে চিন্তাভাবনা শুরু করার পরিবর্তে React.cloneElement ব্যবহার করার বিষয়ে বিবেচনা করার একটি ভাল সুযোগ। আমরা বাস্তবে এটি অপসারণের আগে অবচয় বিজ্ঞপ্তিগুলি সহ একটি রিলিজ প্রেরণ নিশ্চিত করব যাতে তাত্ক্ষণিক কোনও পদক্ষেপের প্রয়োজন হয় না।

আরও এখানে ...


17

সেরা উপায়, যা আপনাকে সম্পত্তি স্থানান্তর করতে দেয় childrenএমন একটি ফাংশনের মতো

উদাহরণ:

export const GrantParent = () => {
  return (
    <Parent>
      {props => (
        <ChildComponent {...props}>
          Bla-bla-bla
        </ChildComponent>
      )}
    </Parent>
  )
}

export const Parent = ({ children }) => {
    const somePropsHere = { //...any }
    <>
        {children(somePropsHere)}
    </>
}

1
এটি আমার কাছে গ্রহণযোগ্য উত্তরের চেয়ে আরও সোজা (এবং পারফরম্যান্সের পক্ষে আরও ভাল?) বলে মনে হচ্ছে seems
শিক्यो

2
এটির জন্য বাচ্চাদের একটি ফাংশন হওয়া প্রয়োজন এবং স্বভাবজাত নেস্টেড উপাদানগুলির জন্য কাজ করে না
ডিজিটাল বিভ্রম

@ ডিজিটালিলিউশন, এর অর্থ কী তা আমি বুঝতে পারি না nested components। প্রতিক্রিয়া নেস্টেড নিদর্শন নেই, শুধুমাত্র রচনা। হ্যাঁ, বাচ্চাদের অবশ্যই একটি ফাংশন হতে হবে, কোনও দ্বন্দ্ব নেই, কারণ এটি বৈধ জেএসএক্স শিশু। আপনি একটি উদাহরণ দিতে পারেন nesting components?
নিক ওভচিনিকভ

1
আপনি ঠিক বলেছেন যে গভীরভাবে ঘৃণিত শিশুদের ক্ষেত্রে <Parent>{props => <Nest><ChildComponent /></Nest>}</Parent>(কাজ না করা) এর পরিবর্তে পাশাপাশি পরিচালনা করা যেতে পারে <Parent><Nest>{props => <ChildComponent />}</Nest></Parent>তাই আমি সম্মত হলাম এটিই সেরা উত্তর
ডিজিটাল বিভ্রম

চেষ্টা করার সময় আমি নিম্নলিখিতটি গ্রহণ করি:TypeError: children is not a function
রায়ান প্রেন্টিস

6

আমি এটি ব্যবহার কার্যকর করতে উপরে গৃহীত উত্তর ঠিক করা প্রয়োজন যে পরিবর্তে এই পয়েন্টার। এই মানচিত্র ফাংশন সুযোগ মধ্যে ছিল না doSomething ম ফাংশন পূর্বনির্ধারণ।

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 এ ভার = এর প্রয়োজন নেই


13
বা কেবল ব্যবহার করুনbind()
প্লাস-

1
বা লেসিকাল স্কোপকে আবদ্ধ করে এমন একটি তীর ফাংশন ব্যবহার করুন, আমি আমার উত্তর আপডেট করেছি
ডমিনিক

কি যদি doSomethingকোনও বস্তু গ্রহণ করে, যেমন doSomething: function(obj) { console.log(obj) }সন্তানের মতো এবং this.props.doSomething(obj)আপনি লগ আউট করার জন্য কল করতে চান"obj"
conor909

4
@ প্লাস- আমি জানি এটি পুরানো, তবে এখানে বাঁধাই ব্যবহার করা একটি ভয়ানক ধারণা, বাইন্ড একটি নতুন ফাংশন তৈরি করে যা প্রসঙ্গে একটি নতুনকে আবদ্ধ করে। মূলত একটি ফাংশন applyপদ্ধতি কলিং । bind()রেন্ডার ফাংশনটি ব্যবহার করে প্রতিবার রেন্ডার পদ্ধতিটি ডাকা হলে একটি নতুন ফাংশন তৈরি হবে।
বামিহ

6

এক বা একাধিক শিশু বিবেচনা করে পরিষ্কার উপায় Clean

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

এটি আমার জন্য কাজ করে না, এটি একটি ত্রুটি দেয়: বাচ্চারা সংজ্ঞায়িত হয় না।
ডিলাক্স

বাচ্চাদের পরিবর্তে ডিলাক্স এই.প্রোপস.চিল্ডেন
মার্টিন ডসন

এটি শিশুকে তার নিজের সন্তান হিসাবে পাস করে this.props। সাধারণভাবে আমি কেবল নির্দিষ্ট প্রপস দিয়ে ক্লোনিংয়ের পরামর্শ দিই, পুরো শেবাং নয়।
অ্যান্ডি

পাসিং {...this.props}আমার পক্ষে কাজ করে না, উপায় কি {...child.props}সঠিক?
ফিলিপ অগস্টো

কার্যকরী উপাদানগুলির জন্য:React.Children.map(children, child => React.cloneElement(child, props))
vsync

5

উত্তরের কোনওটিই সন্তানের জন্মদানের সমস্যাটিকে সম্বোধন করে না যেমন পাঠ্য স্ট্রিংয়ের মতো উপাদানগুলি প্রতিক্রিয়া করে না । একটি workaround কিছু হতে পারে:

// 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>

}

5

আপনার আর দরকার নেই {this.props.children}। এখন আপনি ব্যবহার করে আপনার সন্তানের উপাদান মোড়ানো পারেন renderমধ্যে Routeএবং স্বাভাবিক ভাবে আপনার সাজসরঞ্জাম পাস:

<BrowserRouter>
  <div>
    <ul>
      <li><Link to="/">Home</Link></li>
      <li><Link to="/posts">Posts</Link></li>
      <li><Link to="/about">About</Link></li>
    </ul>

    <hr/>

    <Route path="/" exact component={Home} />
    <Route path="/posts" render={() => (
      <Posts
        value1={1}
        value2={2}
        data={this.state.data}
      />
    )} />
    <Route path="/about" component={About} />
  </div>
</BrowserRouter>

2
রেন্ডার প্রপসগুলি এখন রিএ্যাক্টের মধ্যে আদর্শ ( reactjs.org/docs/render-props.html ) এবং এই প্রশ্নের জন্য একটি নতুন গৃহীত উত্তর হিসাবে বিবেচনাযোগ্য।
ইয়ান ড্যানফোর্থ

19
এটি প্রশ্নের উত্তর কীভাবে?
ম্যাক্সিমো ডোমিংয়েজ

4

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= পূর্বরূপ


4

সম্ভবত আপনি এই বৈশিষ্ট্যটিও দরকারী খুঁজে পেতে পারেন, যদিও অনেকে এটিকে একটি অ্যান্টি-প্যাটার্ন হিসাবে বিবেচনা করেছেন তবে এটি আপনি এখনও কী ব্যবহার করছেন এবং আপনার সমাধানটি ভালভাবে ডিজাইন করেছেন তা ব্যবহার করা যেতে পারে।

শিশু উপাদান হিসাবে কাজ


এটি কোনও বিরোধী-নিদর্শন নয়: youtube.com/watch?v=BcVAq3YFiuc
পিট্রো কোয়েলহো

4

আপনার যদি একাধিক বাচ্চা থাকে তবে আপনি প্রপসগুলি পাস করতে চান , আপনি প্রতিক্রিয়া.চিল্ডারন.ম্যাপ ব্যবহার করে এইভাবে এটি করতে পারেন:

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

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

যদি আপনার উপাদানটির একটি মাত্র শিশু হয় তবে ম্যাপিংয়ের দরকার নেই, আপনি সরাসরি ক্লোনইলেট করতে পারেন সরাসরি:

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

3

এর ডকুমেন্টেশন অনুযায়ী cloneElement()

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

ক্লোন করুন এবং প্রারম্ভিক পয়েন্ট হিসাবে উপাদান ব্যবহার করে একটি নতুন প্রতিক্রিয়া উপাদান ফিরে। ফলস্বরূপ উপাদানটির মূল উপাদানগুলির প্রপস অল্প পরিমাণে মিশে যাওয়া নতুন প্রপগুলির সাথে থাকবে। নতুন শিশুরা বিদ্যমান বাচ্চাদের প্রতিস্থাপন করবে। মূল উপাদান থেকে কী এবং রেফ সংরক্ষণ করা হবে।

React.cloneElement() প্রায় সমতুল্য:

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

তবে এটি রেফগুলিও সংরক্ষণ করে। এর অর্থ হ'ল আপনি যদি কোনও সন্তানের সাথে এটির উপর নির্ভর করে পান তবে আপনি দুর্ঘটনাক্রমে আপনার পূর্বপুরুষের কাছ থেকে এটি চুরি করবেন না। আপনি আপনার নতুন উপাদানের সাথে একই রেফ সংযুক্ত পাবেন।

তাই ক্লোন এলিমেন্টটি হ'ল আপনি বাচ্চাদের কাস্টম প্রপস সরবরাহ করতে ব্যবহার করবেন। তবে উপাদানটিতে একাধিক শিশু থাকতে পারে এবং এটির উপর আপনাকে লুপ করতে হবে। আপনি তাদের ব্যবহার উপর ম্যাপ জন্য আর কি কি উত্তর সুপারিশ করা হয় React.Children.map। তবে React.Children.mapঅসদৃশ React.cloneElementপরিবর্তন উপাদান কি সংযোজন এবং অতিরিক্ত .$উপসর্গ হিসাবে। আরও তথ্যের জন্য এই প্রশ্নটি পরীক্ষা করুন: React.Children.map এর অভ্যন্তরে React.cloneElement উপাদান উপাদানগুলি পরিবর্তন করার কারণ করছে

আপনি এটা এড়ানোর করতে চান, আপনি যদি এর পরিবর্তে জন্য যেতে হবে forEachমত ফাংশন

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

}

2

@ এবং_রেস্ট উত্তরে আরও, এইভাবে আমি বাচ্চাদের ক্লোন করে একটি ক্লাস যুক্ত করি।

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

2

আমি মনে করি একটি রেন্ডার প্রপ এই দৃশ্যটি পরিচালনা করার উপযুক্ত উপায়

এরকম কোনও কিছুর দিকে নজর দেওয়ার জন্য প্যারেন্ট কোডটি রিফ্যাক্টর করে আপনি পিতামাতাকে সন্তানের উপাদানগুলিতে প্রয়োজনীয় প্রসেস সরবরাহ করতে দিন:

const Parent = ({children}) => {
  const doSomething(value) => {}

  return children({ doSomething })
}

তারপরে সন্তানের অংশে আপনি পিতামাতার প্রদত্ত ফাংশনটি এইভাবে অ্যাক্সেস করতে পারবেন:

class Child extends React {

  onClick() => { this.props.doSomething }

  render() { 
    return (<div onClick={this.onClick}></div>);
  }

}

এখন বাগদত্তা স্ট্যাকচারটি দেখতে এরকম হবে:

<Parent>
  {(doSomething) =>
   (<Fragment>
     <Child value="1" doSomething={doSomething}>
     <Child value="2" doSomething={doSomething}>
    <Fragment />
   )}
</Parent>

2

পদ্ধতি 1 - ক্লোন শিশু

const Parent = (props) => {
   const attributeToAddOrReplace= "Some Value"
   const childrenWithAdjustedProps = React.Children.map(props.children, child =>
      React.cloneElement(child, { attributeToAddOrReplace})
   );

   return <div>{childrenWithAdjustedProps }</div>
}

পদ্ধতি 2 - কম্পোজেবল প্রসঙ্গ ব্যবহার করুন

প্রসঙ্গ আপনাকে মধ্যবর্তী উপাদানগুলির মাধ্যমে স্পষ্টভাবে প্রপস হিসাবে প্রেরণ না করে গভীর শিশু উপাদানগুলির কাছে একটি প্রপস পাস করার অনুমতি দেয়।

প্রসঙ্গটি ত্রুটিগুলি সহ আসে:

  1. প্রপসের মাধ্যমে - ডেটা নিয়মিতভাবে প্রবাহিত হয় না।
  2. প্রসঙ্গ ব্যবহার করা গ্রাহক এবং সরবরাহকারীর মধ্যে একটি চুক্তি তৈরি করে। কোনও উপাদান পুনঃব্যবহারের জন্য প্রয়োজনীয় প্রয়োজনীয়তাগুলি বোঝা এবং প্রতিলিপি করা আরও কঠিন হতে পারে।

একটি কম্পোজেবল প্রসঙ্গ ব্যবহার করা

export const Context = createContext<any>(null);

export const ComposableContext = ({ children, ...otherProps }:{children:ReactNode, [x:string]:any}) => {
    const context = useContext(Context)
    return(
      <Context.Provider {...context} value={{...context, ...otherProps}}>{children}</Context.Provider>
    );
}

function App() {
  return (
      <Provider1>
            <Provider2> 
                <Displayer />
            </Provider2>
      </Provider1>
  );
}

const Provider1 =({children}:{children:ReactNode}) => (
    <ComposableContext greeting="Hello">{children}</ComposableContext>
)

const Provider2 =({children}:{children:ReactNode}) => (
    <ComposableContext name="world">{children}</ComposableContext>
)

const Displayer = () => {
  const context = useContext(Context);
  return <div>{context.greeting}, {context.name}</div>;
};

কিছুটা দেরি হয়ে গেছে, তবে আপনি কি স্বরলিপিটি ব্যাখ্যা করতে পারেন {children}:{children:ReactNode}?
ক্যামিল

@ ক্যামিল, এটি একটি টাইপস্ক্রিপ্ট জিনিস। এখন এটি দেখার জন্য, আমি কেবল জাভাস্ক্রিপ্টের সাথে উত্তর দেব, এবং এমনকি টাইপস্ক্রিপ্ট লিখতে চাইলেও আমি এটি অন্যভাবে করব। ভবিষ্যতে এটি সম্পাদনা করতে পারে।
বেন কার্প

1
@ ক্যামিল, মূলত এর অর্থ হল যে কীটি রয়েছে তার মানটি "children"টাইপ করা হয়েছেReactNode
বেন কার্প

1

এটি করার সবচেয়ে সহজ উপায়:

    {React.cloneElement(this.props.children, this.props)}

5
এটি কি এই.প্রেস.চিল্ডারদের সন্তানের এই.পড়গুলি.কিলড্রেনগুলিতে অনুলিপি করে না? এবং কার্যত নিজের মধ্যে শিশুটিকে অনুলিপি করছেন?
আরশভ আগরওয়াল

1

যার একক সন্তানের উপাদান রয়েছে তার পক্ষে এটি করা উচিত।

{React.isValidElement(this.props.children)
                  ? React.cloneElement(this.props.children, {
                      ...prop_you_want_to_pass
                    })
                  : null}

0

এই আপনার প্রয়োজন কি?

var Parent = React.createClass({
  doSomething: function(value) {
  }
  render: function() {
    return  <div>
              <Child doSome={this.doSomething} />
            </div>
  }
})

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

4
নাহ, আমি আমার মোড়কের লিখিত সামগ্রীটি নির্দিষ্ট নির্দিষ্ট সামগ্রীতে সীমাবদ্ধ রাখতে চাই না।
প্লাস-

0

কিছু কারণ 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 । আপনি একইভাবে যে কোনও প্রপ পাস করতে পারেন


0

প্রপার্স রেন্ডার হ'ল এই সমস্যার সবচেয়ে সঠিক পন্থা approach শিশুদের প্রপস হিসাবে সন্তানের উপাদানটি পিতামাতার উপাদানগুলিতে স্থান দেওয়ার পরিবর্তে, পিতামাতাকে ম্যানুয়ালি সন্তানের উপাদান সরবরাহ করতে দিন। রেন্ডারটি প্রতিক্রিয়ায় অন্তর্নির্মিত প্রপস থাকে যা ফাংশন প্যারামিটার নেয়। এই ফাংশনটিতে আপনি কাস্টম প্যারামিটারগুলির সাথে প্যারেন্ট উপাদানকে যা চান তা রেন্ডার করতে পারেন। মূলত এটি চাইল্ড প্রপসের মতো একই কাজ করে তবে এটি আরও স্বনির্ধারিত।

class Child extends React.Component {
  render() {
    return <div className="Child">
      Child
      <p onClick={this.props.doSomething}>Click me</p>
           {this.props.a}
    </div>;
  }
}

class Parent extends React.Component {
  doSomething(){
   alert("Parent talks"); 
  }

  render() {
    return <div className="Parent">
      Parent
      {this.props.render({
        anythingToPassChildren:1, 
        doSomething: this.doSomething})}
    </div>;
  }
}

class Application extends React.Component {
  render() {
    return <div>
      <Parent render={
          props => <Child {...props} />
        }/>
    </div>;
  }
}

কোডেপেন এ উদাহরণ


0

ক্রিয়ামূলক উপাদান ব্যবহার TypeError: Cannot add property myNewProp, object is not extensibleকরার সময়, নতুন বৈশিষ্ট্যগুলি সেট করার চেষ্টা করার সময় আপনি প্রায়শই ত্রুটি পাবেন props.children। প্রপস ক্লোন করে এবং তারপরে নতুন প্রপস দিয়ে শিশুটিকে নিজেই ক্লোন করে এটির কাজ রয়েছে।

const MyParentComponent = (props) => {
  return (
    <div className='whatever'>
      {props.children.map((child) => {
        const newProps = { ...child.props }
        // set new props here on newProps
        newProps.myNewProp = 'something'
        const preparedChild = { ...child, props: newProps }
        return preparedChild
      })}
    </div>
  )
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.