Як передавати реквізит {this.props.children}


888

Я намагаюся знайти правильний спосіб визначити деякі компоненти, які можна було б використовувати загальним чином:

<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')
);

Fiddle: 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>або просто <>ви також можете повернути масив, якщо вам зручніше.

Fiddle: https://jsfiddle.net/ferahl/y5pcua68/7/


7
Це не працює для мене. це не визначено в React.cloneElement ()
Патрік

12
Ця відповідь не працює, valueпередана на програму doSomethingвтрачається.
Дейв

3
@DominicTobias Arg, вибачте, я переключив console.log на попередження і забув присвоїти два параметри до одного рядка.
Дейв

1
Ця відповідь була надзвичайно корисною, але я зіткнувся з проблемою, про яку тут не йдеться, і мені було цікаво, чи це щось нове, що змінилося, чи це щось дивне в моєму кінці. Коли я клонував свій дочірній елемент, його дитина встановлюється на старий елемент, поки я не додав цей.props.children.props.children до третього аргументу cloneElement.
афенін

7
Що робити, якщо дитина завантажена через маршрут (v4), завантажений із окремої сторінки маршруту?
блам

394

Для трохи більш чистого способу це зробити:

<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
Я використовував найбільш оцінену відповідь, але ця набагато прямо вперед! Це рішення також є тим, що вони використовують на сторінці прикладів маршрутизаторів реакцій.
captDaylight

10
Чи може хтось пояснити, як це працює (або що він насправді робить)? Читаючи документи , я не міг побачити, як це спуститься до дітей, і додав цю підтримку кожній дитині - це те, що вона має намір робити? Якщо це так, то як ми знаємо, що саме це і буде робити? Зовсім не очевидно, що навіть неправомірно передавати непрозору структуру даних ( this.props.children) до cloneElement..., що очікує на ... елемент.
GreenAsJade

51
Саме це, здається, не працює з більш ніж однією дитиною.
Даніта

17
Таким чином, ви можете написати код, який працює, коли хтось передає лише одну дитину в компонент, але коли вони додають іншу, вона виходить з ладу ... це не чудово звучить за номіналом? Здавалося б, це пастка для ОП, яка спеціально розпитувала про передачу реквізиту всім дітям.
GreenAsJade

10
@GreenAsJade добре, поки ваш компонент очікує на єдину дитину. За допомогою компонентів propTypes ви можете визначити, що він очікує на одну дитину. React.Children.onlyфункція повертає єдину дочірню або викидає виняток, якщо їх декілька (цього не було б, якби не було випадку використання).
Камберлен

80

Спробуйте це

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

Це працювало для мене, використовуючи реакцію-15.1.


3
Чи можна повернутися React.cloneElement()безпосередньо, не оточуючи його <div>тегами? Бо що робити, якщо дитина - це <span>(або щось інше), і ми хочемо зберегти його тип елемента тегів?
adrianmc

1
Якщо це одна дитина, ви можете залишити обгортку, і це рішення працює лише для однієї дитини, так що так.
ThaJay

1
Працює для мене. Без додавання <div> це нормально.
Crash Override

4
Якщо вам потрібно чітко встановити, що ви отримуєте лише одну дитину, ви можете зробити це, React.cloneElement(React.Children.only(this.props.children), {...this.props})яке призведе до помилки, якщо вона передається більше ніж одній дитині. Тоді вам не потрібно загортатись у діву.
itsananderson

1
Ця відповідь може призвести до значення циклічного об'єкта TypeError: Якщо ви не хочете, щоб один із реквізитів дитини був самим собою, використовуйте let {children, ...acyclicalProps} = this.propsі тоді React.cloneElement(React.Children.only(children), acyclicalProps).
Параболорд

68

Передайте реквізити, щоб направити дітей.

Дивіться всі інші відповіді

Передайте спільні глобальні дані через дерево компонентів через контекст

Контекст призначений для обміну даними, які можна вважати "глобальними" для дерева компонентів React, таких як поточний аутентифікований користувач, тема або бажана мова. 1

Відмова: Це оновлена ​​відповідь, попередня використовувала старий контекстний API

Він заснований на принципі споживача / надання. Спочатку створіть свій контекст

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

Потім використовуйте через

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

і

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

Усі Споживачі, які є нащадками Постачальника, повторно надаватимуть кожного разу, коли значення Постачальника зміниться. Поширення від Постачальника до його нащадків Споживачам не підлягає методу shouldComponentUpdate, тому Споживач оновлюється, навіть коли компонент предка не виходить із оновлення. 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
На відміну від прийнятої відповіді, це працюватиме належним чином навіть тоді, коли під Батьком є ​​інші елементи, включені. Це, безумовно, найкраща відповідь.
Zaptree

6
Реквізит! = Контекст
Петро Пеллер

Ви не можете залежати від змін, що поширюються через контекст. Використовуйте реквізит, коли можливо, вони змінюються.
ThaJay

1
Можливо, я не розумію, але чи не неправильно сказати "контекст робить реквізит доступним"? Коли я востаннє використовував контекст, це була окрема річ (тобто this.context) - вона не магічно зливала контекст із реквізитом. Вам довелося навмисно встановлювати та використовувати контекст, що зовсім інша річ.
Джош

Ви прекрасно розумієте, це було неправильно. Я відредагував свою відповідь.
Любомир

48

Передача реквізиту вкладеним дітям

З оновленням до React 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контексту
Кеннет Труонг,

@KennethTruong, тому що кожного разу він створює функцію.
itdoesntwork

9
@itdoesntwork це неправда. Він створює нову функцію лише тоді, коли створюється клас. Його не створюють під час візуалізації ..
Кеннет Труонг

@KennethTruong reactjs.org/docs/faq-functions.html#arrow-function-in-render Я думав, ви говорили про функцію стрілки в візуалізації.
itdoesntwork

24

Ви можете використовувати React.cloneElement, краще знати, як це працює, перш ніж почати використовувати його у своїй програмі. Він представлений React v0.13, читайте далі для отримання додаткової інформації, тож щось разом із цією роботою для вас:

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

Тому принесіть рядки з документації React, щоб зрозуміти, як це все працює і як ви можете ними скористатися:

У React v0.13 RC2 ми представимо новий API, схожий на React.addons.cloneWithProps, з таким підписом:

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

На відміну від cloneWithProps, ця нова функція не має ніякої магічної вбудованої поведінки для злиття стилю та className з тієї ж причини, що у нас немає цієї функції від transferPropsTo. Ніхто не впевнений, що саме являє собою повний перелік магічних речей, що ускладнює міркування про код і важке повторне використання, коли стиль має інший підпис (наприклад, у майбутньому 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 (дочірня, {ref: 'newRef'}) НЕ переосмислює реф.

Це було важливою особливістю потрапити в React 0.13, оскільки реквізит незмінний. Шлях до оновлення часто клонує елемент, але тим самим ви можете втратити посилання. Тому тут нам знадобився приємніший шлях оновлення. Під час оновлення викликів у Facebook ми зрозуміли, що нам потрібен цей метод. Ми отримали такі ж відгуки від громади. Тому ми вирішили зробити ще один RC перед остаточним випуском, щоб переконатися, що ми це отримаємо.

Ми плануємо врешті-решт знищити React.addons.cloneWithProps. Ми цього ще не робимо, але це хороша можливість почати думати про власні використання та розглянути можливість використання React.cloneElement. Ми обов’язково доставлятимемо випуск із повідомленнями про депресію, перш ніж ми його фактично видалимо, тому негайних дій не потрібно.

докладніше тут ...


18

Найкращий спосіб, який дозволяє здійснити передачу власності - це childrenяк функція

Приклад:

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

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

1
Це здається мені більш простим (а краще для продуктивності?) Для мене, ніж прийнята відповідь.
Шикіо

2
Це вимагає від дітей функції і не працює для деліптованих вкладених компонентів
цифрова ілюзія

@digitalillusion, я не розумію, що це означає nested components. React не має вкладених шаблонів, лише композиції. Так, діти повинні бути функцією, конфліктів немає, тому що це дійсна дитина JSX. Чи можете ви навести приклад 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 немає необхідності в var що = це


13
або просто використовуватиbind()
плюс-

1
або скористатися функцією зі стрілками, яка прив'язується до лексичної сфери, я оновив свою відповідь
Домінік

що робити, якщо ви doSomethingвзяли предмет, як-от doSomething: function(obj) { console.log(obj) }і в дитині ви зателефонували this.props.doSomething(obj)б вийти"obj"
conor909

4
@ плюс - я знаю, що це давнє, але використання bind тут - жахлива ідея, bind створює нову функцію, яка прив'язує контекст до нової. в основному функція, що викликає applyметод. використання bind()функції візуалізації створюватиме нову функцію щоразу, коли викликається метод візуалізації.
Bamieh

6

Чистіший спосіб розгляду одного або декількох дітей

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

Цей для мене не працює, він дає помилку: діти не визначені.
Deelux

@Deelux this.props.children замість дітей
Мартін Доусон

це передає дитину як її власних дітей this.props. Взагалі я б рекомендував клонувати лише конкретними реквізитами, а не цілим шебангом.
Енді

Проїзд {...this.props}не працював для мене, чи {...child.props}правильний спосіб ?
Феліпе Аугусто

Для функціональних компонентів:React.Children.map(children, child => React.cloneElement(child, props))
vsync

5

Жодна з відповідей не стосується питання наявності дітей, які НЕ реагують компонентами, такими як текстові рядки. Обхід може бути приблизно таким:

// 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
Реквізити для візуалізації тепер стандартні в React ( 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=preview


4

Можливо, ви також можете знайти корисну цю функцію, хоча багато людей розглядали це як анти-шаблон, але він все-таки може бути використаний, якщо ви знаєте, що робите, і добре розробляєте рішення.

Функція як дочірні компоненти


Це не анти-шаблон: youtube.com/watch?v=BcVAq3YFiuc
Pietro Coelho

4

Якщо у вас є кілька дітей, яким ви хочете передати реквізит , ви можете це зробити так, використовуючи React.Children.map:

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

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

Якщо ваш компонент має лише одну дитину, картографування не потрібно, ви можете просто клонуватиElement відразу:

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

3

Відповідно до документації о cloneElement()

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

Клонуйте і поверніть новий елемент React, використовуючи елемент як вихідну точку. Отриманий елемент матиме реквізити оригінального елемента з новими реквізитами, об'єднаними неглибоко. Нові діти замінять існуючих дітей. ключ та ref від початкового елемента будуть збережені.

React.cloneElement() майже еквівалентний:

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

Однак він також зберігає реф. Це означає, що якщо ви отримаєте дитину зі списком, ви її випадково не вкрадете у свого предка. Ви отримаєте ту саму посилання, яка додається до вашого нового елемента.

Отже, cloneElement - це те, що ви використовували б для надання дітям реквізиту. Однак у компоненті може бути декілька дітей, і вам потрібно буде перевернути його. Інші відповіді пропонують вам скласти карту, використовуючи їх React.Children.map. Однак на 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>
    )

}

2

Далі до відповіді @and_rest, я клоную дітей та додаю клас.

<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}?
Каміль

@camille, це тип машинопису. Дивлячись на це зараз, я просто відповів би Javascript, і навіть якби я написав Typescript, я зробив би це по-іншому. Можливо, відредагуйте це в майбутньому.
Бен Карп

1
@camille, в основному це означає, що значення, яке має ключ, "children"має типReactNode
Бен Карп

1

Найкруткіший спосіб зробити це:

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

5
Це не скопіює this.props.children у this.props.children дитини? а фактично копіюючи дитину в себе?
Аршабх Агарвал

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

Надання реквізиту є найбільш точним підходом до цієї проблеми. Замість того, щоб передавати дочірній компонент батьківському компоненту як дочірній реквізит, дозвольте батькові відображати дочірній компонент вручну. Render - це вбудований реквізит у реакції, який приймає параметр функції. За допомогою цієї функції ви можете дозволити батьківському компоненту відображати все, що завгодно, із спеціальними параметрами. В основному це робить те ж саме, що і дитячий реквізит, але це більш настроюється.

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>;
  }
}

Приклад у codepen


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>
  )
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.