Ainda sou um novato no React e em muitos exemplos na internet, vejo essa variação na renderização de elementos filhos que considero confusa. Normalmente eu vejo isso:
class Users extends React.Component {
render() {
return (
<div>
<h2>Users</h2>
{this.props.children}
</div>
)
}
}
Mas então vejo um exemplo como este:
<ReactCSSTransitionGroup
component="div"
transitionName="example"
transitionEnterTimeout={500}
transitionLeaveTimeout={500}
>
{React.cloneElement(this.props.children, {
key: this.props.location.pathname
})}
</ReactCSSTransitionGroup>
Agora eu entendo a API, mas os documentos não deixam exatamente claro quando devo usá-la.
Então, o que um faz que o outro não pode? Alguém poderia me explicar isso com melhores exemplos?
Respostas:
Editar:
Olhe para a resposta de Vennesa em vez disso, que é uma explicação melhor.
Original:
Em primeiro lugar, o
React.cloneElement
exemplo só funciona se seu filho for um único elemento React.Pois quase tudo
{this.props.children}
é o que você deseja. A clonagem é útil em alguns cenários mais avançados, onde um pai envia um elemento e o componente filho precisa alterar alguns adereços nesse elemento ou adicionar coisas como ref para acessar o elemento DOM real.No exemplo acima, o pai que fornece ao filho não sabe sobre o requisito de chave para o componente, portanto, ele cria uma cópia do elemento que é fornecido e adiciona uma chave com base em algum identificador único no objeto. Para obter mais informações sobre o que a chave faz: https://facebook.github.io/react/docs/multiple-components.html
fonte
props.children
não são os filhos reais; É odescriptor
dos filhos. Então, você não tem realmente nada para mudar; você não pode alterar nenhum adereço ou editar qualquer funcionalidade; você só poderead from it
. Se você precisar fazer qualquer modificação, deverá criarnew elements
usandoReact.CloneElement
.https://egghead.io/lessons/react-use-react-cloneelement-to-extend-functionality-of-children-components
Um exemplo:
função de renderização principal de um componente, como
App.js
:agora, digamos que você precise adicionar um
onClick
a cada filho deParagraph
; então em seuParagraph.js
você pode fazer:então, simplesmente você pode fazer isso:
Nota: a
React.Children.map
função verá apenas ostop level
elementos, ela não verá nenhuma das coisas que esses elementos renderizam; o que significa que você está fornecendo os acessórios diretos para as crianças (aqui os<Sentence />
elementos). Se você precisar que os adereços sejam passados adiante, digamos que você tenha um<div></div>
dentro de um dos<Sentence />
elementos que deseja usar oonClick
adereço, então, nesse caso, você pode usar oContext API
para fazê-lo. Faça doParagraph
provedor e dosSentence
elementos como consumidor.fonte
React.Children.map
em conjunto comReact.cloneElement
@vennesa aponta, é muito poderosoNa verdade,
React.cloneElement
não está estritamente associadothis.props.children
.É útil sempre que você precisa clonar os elementos react (
PropTypes.element
) para adicionar / sobrescrever props, sem querer que o pai tenha conhecimento sobre os componentes internos (por exemplo, anexar manipuladores de eventos ou atribuirkey
/ref
atributos).Além disso, os elementos reactivos são imutáveis .
No entanto, o
children
prop no React é especialmente usado para contenção (também conhecido como composição ), emparelhamento comReact.Children
API eReact.cloneElement
, componente que usa props.children pode lidar com mais lógica (por exemplo, transições de estado, eventos, medições de DOM etc) internamente enquanto produz a parte de renderização para onde quer que seja usado, React Router<switch/>
ou componente composto<select/>
são alguns ótimos exemplos.Uma última coisa que vale a pena mencionar é que os elementos de reação não se restringem a props.children.
Eles podem ser o que adereços que faz sentido, a chave foi definir um contrato bom para o componente, de modo que os consumidores de que pode ser dissociado dos detalhes de implementação subjacentes, independentemente se ele está usando
React.Children
,React.cloneElement
ou até mesmoReact.createContext
.fonte