Коли я повинен використовувати React.cloneElement vs this.props.children?


118

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

class Users extends React.Component {
  render() {
    return (
      <div>
        <h2>Users</h2>
        {this.props.children}
      </div>
    )
  }
}

Але тоді я бачу такий приклад:

<ReactCSSTransitionGroup
     component="div"
     transitionName="example"
     transitionEnterTimeout={500}
     transitionLeaveTimeout={500}
     >
     {React.cloneElement(this.props.children, {
       key: this.props.location.pathname
      })}
</ReactCSSTransitionGroup>

Тепер я розумію api, але документи точно не дають зрозуміти, коли я повинен його використовувати.

Отже, що робить те, чого не може другий? Чи може хтось пояснити це мені кращими прикладами?


3
youtube.com/watch?v=hEGg-3pIHlE цей хлопець показує, як він використовує cloneElement. Перевірте це на деяких прикладах
Iurii

Відповіді:


69

Редагувати:

Подивіться замість відповіді Веннеси , що є кращим поясненням.

Оригінал:

Перш за все, React.cloneElement приклад працює лише в тому випадку, якщо ваша дитина є єдиним елементом React.

Майже на все {this.props.children} - саме те, що ти хочеш. Клонування корисно в деяких більш вдосконалених сценаріях, коли батько надсилає елемент, а дочірньому компоненту потрібно змінити деякі реквізити цього елемента або додати такі речі, як ref для доступу до фактичного елемента DOM.

У наведеному вище прикладі батько, який дає дитині, не знає про ключову вимогу до компонента, тому він створює копію елемента, який йому надається, і додає ключ на основі якогось унікального ідентифікатора в об'єкті. Для отримання додаткової інформації про те, що робить ключ: https://facebook.github.io/react/docs/multiple-components.html


183

props.childrenне справжні діти; Цеdescriptor від дітей. Отже, у вас насправді нічого не можна змінити; ви не можете змінювати реквізити чи редагувати будь-які функції; можна тільки read from it. Якщо вам потрібно внести будь-які зміни, які вам доведеться створити new elementsза допомогою React.CloneElement.

https://egghead.io/lessons/react-use-react-cloneelement-to-extend-functionality-of-children-components

Приклад:

основна функція візуалізації такого компонента, як App.js:

render() {   
    return(
            <Paragraph>
              <Sentence>First</Sentence>
              <Sentence>Second</Sentence>
              <Sentence>Third</Sentence>
            </Paragraph>   
    ) 
}

тепер скажімо, що потрібно додати onClickкожну дитину Paragraph; тож у своєму Paragraph.jsможна зробити:

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

то просто ви можете це зробити:

render() {   
  return(
        <Paragraph onClick={this.onClick}>
          <Sentence>First</Sentence>
          <Sentence>Second</Sentence>
          <Sentence>Third</Sentence>
        </Paragraph>   
   ) 
}

Примітка:React.Children.map функція буде бачити тільки top levelелементи, він не бачить будь - яку з речей , що ці елементи роблять; це означає, що ви надаєте дітям прямий реквізит (тут <Sentence />елементи). Якщо вам потрібен реквізит, який слід передавати далі, скажімо, у вас буде <div></div>всередині одного з <Sentence />елементів, який хоче використовувати onClickопору, то в такому випадку ви можете використовувати Context APIдля цього. Зробіть Paragraphпостачальника та Sentenceелементи споживачами.


11
Це чітка відповідь на прикладі реального світу. На це потрібно більше грошей.
SeaWarrior404

1
Погодьтеся з @ SeaWarrior404 - я б здогадався, що ОП шукає ітерації над колекцією, а не однією дитиною, оскільки його інтерфейс користувача має назву "Користувачі" / множина. Використання React.Children.mapспільно з, React.cloneElementяк вказує @vennesa, дуже потужне
jakeforaker

23

Насправді React.cloneElementце не суворо пов'язано з this.props.children.

Це корисно, коли вам потрібно клонувати елементи реагування ( PropTypes.element), щоб додати / змінити реквізити, не бажаючи, щоб батьки мали знання про внутрішні компоненти компонентів (наприклад, приєднання обробників подій або призначення key/ refатрибутів).

Також реагують елементи незмінні .

React.cloneElement (елемент, [реквізит], [... діти]) майже еквівалентний: <element.type {...element.props} {...props}>{children}</element.type>


Однак, childrenопора в React особливо використовується для стримування (ака композиції ), сполучення з React.ChildrenAPI і React.cloneElementкомпонента, який використовує props.children може обробляти більше логіки (наприклад, переходи стану, події, вимірювання DOM тощо) внутрішньо, віддаючи частину візуалізації де б він не використовувався, React Router <switch/>або складний компонент - <select/>це чудові приклади.

Останнє, що варто згадати, - це те, що елементи реагування не обмежуються дітьми props.children.

function SplitPane(props) {
  return (
    <div className="SplitPane">
      <div className="SplitPane-left">
        {props.left}
      </div>
      <div className="SplitPane-right">
        {props.right}
      </div>
    </div>
  );
}

function App() {
  return (
    <SplitPane
      left={
        <Contacts />
      }
      right={
        <Chat />
      } />
  );
}

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

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