J'essaie de trouver la bonne façon de définir certains composants qui pourraient être utilisés de manière générique:
<Parent>
<Child value="1">
<Child value="2">
</Parent>
Il y a une logique en cours pour le rendu entre les composants parents et enfants bien sûr, vous pouvez l'imaginer <select>
et <option>
comme exemple de cette logique.
Il s'agit d'une implémentation factice aux fins de la question:
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>);
}
});
La question est chaque fois que vous utilisez {this.props.children}
pour définir un composant wrapper, comment transmettez-vous une propriété à tous ses enfants?
javascript
reactjs
react-jsx
plus-
la source
la source
Réponses:
Clonage d'enfants avec de nouveaux accessoires
Vous pouvez utiliser React.Children pour parcourir les enfants, puis cloner chaque élément avec de nouveaux accessoires (peu profonds fusionnés) à l'aide de React.cloneElement, par exemple:
Violon: https://jsfiddle.net/2q294y43/2/
Appel des enfants en fonction
Vous pouvez également transmettre des accessoires aux enfants avec des accessoires de rendu . Dans cette approche, les enfants (qui peuvent être
children
ou tout autre nom d'accessoire) est une fonction qui peut accepter tous les arguments que vous souhaitez transmettre et renvoie les enfants:Au lieu de
<React.Fragment>
ou simplement,<>
vous pouvez également retourner un tableau si vous préférez.Violon: https://jsfiddle.net/ferahl/y5pcua68/7/
la source
value
passédoSomething
est perdu.Pour une façon légèrement plus propre de le faire, essayez:
Modifier: Pour utiliser avec plusieurs enfants individuels (l'enfant doit lui-même être un composant), vous pouvez le faire. Testé en 16.8.6
la source
this.props.children
) àcloneElement
... qui attend un ... élément.React.Children.only
La fonction renvoie le seul enfant ou lève une exception s'il y en a plusieurs (cela n'existerait pas s'il n'y avait pas de cas d'utilisation).Essaye ça
Cela a fonctionné pour moi en utilisant react-15.1.
la source
React.cloneElement()
directement sans l'entourer de<div>
balises? Parce que si l'enfant est un<span>
(ou quelque chose d'autre) et que nous voulons conserver son type d'élément tag?React.cloneElement(React.Children.only(this.props.children), {...this.props})
ce qui générera une erreur si plusieurs enfants lui sont transmis. Ensuite, vous n'avez pas besoin d'envelopper dans un div.let {children, ...acyclicalProps} = this.props
puisReact.cloneElement(React.Children.only(children), acyclicalProps)
.Passez des accessoires pour diriger les enfants.
Voir toutes les autres réponses
Passer des données globales partagées à travers l'arborescence des composants via le contexte
Avertissement: il s'agit d'une réponse mise à jour, la précédente utilisait l'ancienne API de contexte
Il est basé sur le principe Consommateur / Fournir. Créez d'abord votre contexte
Utilisez ensuite via
et
Exemple complet, semi-pseudo-code.
1 https://facebook.github.io/react/docs/context.html
la source
this.context
) - il n'a pas fusionné comme par magie le contexte avec les accessoires. Vous avez dû définir et utiliser intentionnellement le contexte, ce qui est tout autre chose.Passer les accessoires aux enfants imbriqués
Avec la mise à jour React 16.6 vous pouvez maintenant utiliser React.createContext et contextType .
la source
this
contexteVous pouvez utiliser
React.cloneElement
, il est préférable de savoir comment cela fonctionne avant de commencer à l'utiliser dans votre application. Il est introduit dansReact v0.13
, lisez la suite pour plus d'informations, donc quelque chose avec ce travail pour vous:Apportez donc les lignes de la documentation React pour que vous compreniez comment tout cela fonctionne et comment vous pouvez les utiliser:
plus ici ...
la source
La meilleure façon, qui vous permet de faire un transfert de propriété, c'est
children
comme une fonctionExemple:
la source
nested components
. React n'a pas de motifs imbriqués, seulement des compositions. Oui, les enfants doivent être une fonction, il n'y a aucun conflit, car c'est un enfant JSX valide. Pouvez-vous donner un exemple avecnesting components
?<Parent>{props => <Nest><ChildComponent /></Nest>}</Parent>
lieu de (ne pas fonctionner),<Parent><Nest>{props => <ChildComponent />}</Nest></Parent>
donc je suis d'accord que c'est la meilleure réponseTypeError: children is not a function
J'avais besoin de corriger la réponse acceptée ci-dessus pour le faire fonctionner en utilisant cela au lieu de ce pointeur. Ce dans le cadre de la fonction de carte n'a pas doSomething fonction définie.
Mise à jour: ce correctif concerne ECMAScript 5, dans ES6 il n'y a pas besoin de var qui = this
la source
bind()
doSomething
sedoSomething: function(obj) { console.log(obj) }
this.props.doSomething(obj)
"obj"
apply
méthode. l'utilisationbind()
de la fonction de rendu créera une nouvelle fonction à chaque appel de la méthode de rendu.Une façon plus propre en considérant un ou plusieurs enfants
la source
this.props
. En général, je ne recommanderais que le clonage avec des accessoires spécifiques, pas l'ensemble du shebang.{...this.props}
n'ont pas fonctionné pour moi, est-ce que c'est{...child.props}
correct?React.Children.map(children, child => React.cloneElement(child, props))
Aucune des réponses ne traite du problème d'avoir des enfants qui ne sont PAS des composants React, tels que des chaînes de texte. Une solution de contournement pourrait être quelque chose comme ceci:
la source
Vous n'en avez plus besoin
{this.props.children}
. Maintenant , vous pouvez envelopper votre composant enfant à l' aiderender
deRoute
et passer vos accessoires comme d' habitude:la source
Parent.jsx:
Child.jsx:
et main.jsx:
voir l'exemple ici: https://plnkr.co/edit/jJHQECrKRrtKlKYRpIWl?p=preview
la source
Peut-être que vous pouvez également trouver cette fonctionnalité utile, bien que de nombreuses personnes aient considéré cela comme un anti-modèle, elle peut toujours être utilisée si vous savez ce que vous faites et concevez bien votre solution.
Fonction en tant que composants enfants
la source
Si vous avez plusieurs enfants auxquels vous souhaitez transmettre des accessoires , vous pouvez le faire de cette façon, en utilisant React.Children.map:
Si votre composant n'a qu'un seul enfant, il n'est pas nécessaire de mapper, vous pouvez simplement clonerElement immédiatement:
la source
Selon la documentation de
cloneElement()
Donc, cloneElement est ce que vous utiliseriez pour fournir des accessoires personnalisés aux enfants. Cependant, il peut y avoir plusieurs enfants dans le composant et vous devrez boucler dessus. Les autres réponses suggèrent que vous puissiez les cartographier à l'aide
React.Children.map
. Cependant,React.Children.map
contrairement à ce quiReact.cloneElement
change, les clés de l'élément sont ajoutées et extra.$
comme préfixe. Consultez cette question pour plus de détails: React.cloneElement dans React.Children.map entraîne la modification des clés d'élémentSi vous souhaitez l'éviter, vous devriez plutôt opter pour la
forEach
fonction commela source
Suite à la réponse @and_rest, voici comment je clone les enfants et ajoute une classe.
la source
Je pense qu'un accessoire de rendu est la façon appropriée de gérer ce scénario
Vous laissez le parent fournir les accessoires nécessaires utilisés dans le composant enfant, en refactorisant le code parent pour ressembler à quelque chose comme ceci:
Ensuite, dans le composant enfant, vous pouvez accéder à la fonction fournie par le parent de cette façon:
Maintenant, la structure fianl ressemblera à ceci:
la source
Méthode 1 - Cloner des enfants
Méthode 2 - utiliser un contexte composable
Le contexte vous permet de passer un accessoire à un composant enfant profond sans le faire passer explicitement comme accessoire à travers les composants entre les deux.
Le contexte présente des inconvénients:
Utiliser un contexte composable
la source
{children}:{children:ReactNode}
?"children"
est de typeReactNode
La façon la plus simple de le faire:
la source
Pour tous ceux qui ont un seul élément enfant, cela devrait le faire.
la source
Est-ce ce dont vous aviez besoin?
la source
Une raison pour laquelle React.children ne travaillait pas pour moi. C'est ce qui a fonctionné pour moi.
Je voulais juste ajouter une classe à l'enfant. similaire à changer un accessoire
L'astuce ici est le React.cloneElement . Vous pouvez passer n'importe quel accessoire de manière similaire
la source
Les accessoires de rendu constituent l'approche la plus précise de ce problème. Au lieu de passer le composant enfant au composant parent comme accessoires enfants, laissez le parent rendre le composant enfant manuellement. Le rendu est des accessoires intégrés dans react, qui prend le paramètre de fonction. Dans cette fonction, vous pouvez laisser le composant parent rendre ce que vous voulez avec des paramètres personnalisés. Fondamentalement, il fait la même chose que les accessoires pour enfants, mais il est plus personnalisable.
Exemple chez codepen
la source
Lorsque vous utilisez des composants fonctionnels, vous obtenez souvent l'
TypeError: Cannot add property myNewProp, object is not extensible
erreur lorsque vous essayez de définir de nouvelles propriétésprops.children
. Il y a un moyen de contourner cela en clonant les accessoires puis en clonant l'enfant lui-même avec les nouveaux accessoires.la source