Подтвердить что ты не робот

Когда я должен использовать React.cloneElement против this.props.children?

Я все еще новичок в 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, но документы не совсем ясно, когда я должен его использовать.

Так что же делать одному, а другому нет? Может ли кто-нибудь объяснить мне лучшие примеры?

4b9b3361

Ответ 1

Редактировать:

Вместо этого посмотрите на ответ Веннесы, что является лучшим объяснением.

Оригинал:

Прежде всего, пример React.cloneElement работает только в том случае, если ваш ребенок является единственным элементом React.

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

В приведенном выше примере родительский элемент, который дает дочерний элемент, не знает о ключевом требовании для компонента, поэтому он создает копию предоставленного ему элемента и добавляет ключ на основе некоторого уникального идентификатора в объекте. Для получения дополнительной информации о том, что делает ключ: https://facebook.github.io/react/docs/multiple-components.html

Ответ 2

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 - потребителем.

Ответ 3

На самом деле, React.cloneElement не связан строго с this.props.children.

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

Также реагирующие элементы являются неизменяемыми.

React.cloneElement(element, [props], [... children]) почти эквивалентен: <element.type {...element.props} {...props}>{children}</element.type>


Тем не менее, children пропа в React особенно используются для локализации (он же состав), сопряжения с React.Children API и 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.