J'ai deux composantes.
- Composant parent
- Composant enfant
J'essayais d'appeler la méthode de l'enfant de Parent, j'ai essayé de cette façon mais je n'ai pas pu obtenir de résultat
class Parent extends Component {
render() {
return (
<Child>
<button onClick={Child.getAlert()}>Click</button>
</Child>
);
}
}
class Child extends Component {
getAlert() {
alert('clicked');
}
render() {
return (
<h1 ref="hello">Hello</h1>
);
}
}
Existe-t-il un moyen d'appeler la méthode de l'enfant du parent?
Remarque: les composants enfant et parent se trouvent dans deux fichiers différents
javascript
reactjs
N8FURY
la source
la source
Réponses:
Tout d'abord, permettez-moi d'exprimer que ce n'est généralement pas la façon de procéder dans React Land. Habituellement, ce que vous voulez faire, c'est transmettre la fonctionnalité aux enfants dans les accessoires et transmettre les notifications des enfants dans les événements (ou mieux encore:)
dispatch
.Mais si vous devez exposer une méthode impérative sur un composant enfant, vous pouvez utiliser des références . N'oubliez pas qu'il s'agit d'une trappe d'évacuation et indique généralement qu'un meilleur design est disponible.
Utilisation de crochets et de composants de fonction (
>= [email protected]
)La documentation pour
useImperativeHandle()
est ici :Utilisation des composants de classe (
>= [email protected]
)API héritée (
<= [email protected]
)À des fins historiques, voici le style basé sur le rappel que vous utiliseriez avec les versions React antérieures à 16.3:
la source
connect
renvoie un composant d'ordre supérieur qui enveloppe votre instance d'origine. Vous devrez d'abord appelergetWrappedInstance()
le composant connecté pour obtenir votre composant d'origine. Ensuite, vous pouvez appeler des méthodes d'instance à ce sujet.componentWillReceiveProps
, et l'utiliser comme déclencheur.Vous pouvez utiliser un autre modèle ici:
Ce qu'il fait, c'est de définir la
clickChild
méthode du parent lorsque l'enfant est monté. De cette façon, lorsque vous cliquez sur le bouton parent, il appelle celuiclickChild
qui appelle l'enfantgetAlert
.Cela fonctionne également si votre enfant est enveloppé de
connect()
sorte que vous n'avez pas besoin dugetWrappedInstance()
hack.Notez que vous ne pouvez pas l'utiliser
onClick={this.clickChild}
dans parent car lorsque le parent est rendu, l'enfant n'est pas monté etthis.clickChild
n'est donc pas encore attribué. L'utilisationonClick={() => this.clickChild()}
est très bien car lorsque vous cliquez sur le boutonthis.clickChild
doit déjà être attribué.la source
_this2.clickChild is not a function
pourquoi?https://facebook.github.io/react/tips/expose-component-functions.html pour plus de réponses référez-vous ici Méthodes d'appel sur les composants enfants React
En examinant les références du composant "raison", vous cassez l'encapsulation et vous ne pouvez pas refactoriser ce composant sans examiner attentivement tous les endroits où il est utilisé. Pour cette raison, nous recommandons fortement de traiter les références comme privées à un composant, un peu comme l'état.
En général, les données doivent être transmises dans l'arbre via des accessoires. Il y a quelques exceptions à cela (comme appeler .focus () ou déclencher une animation ponctuelle qui ne "change" pas vraiment l'état) mais chaque fois que vous exposez une méthode appelée "set", les accessoires sont généralement un meilleur choix. Essayez de faire en sorte que le composant d'entrée interne s'inquiète de sa taille et de son apparence afin qu'aucun de ses ancêtres ne le fasse.
la source
Méthode alternative avec useEffect:
Parent:
Enfants:
la source
Nous pouvons utiliser les références d'une autre manière
Nous allons créer un élément Parent, il rendra un
<Child/>
composant. Comme vous pouvez le voir, le composant qui sera rendu, vous devez ajouter l' attribut ref et lui donner un nom.Ensuite, la
triggerChildAlert
fonction, située dans la classe parente, accédera à la propriété refs de ce contexte (lorsque latriggerChildAlert
fonction sera déclenchée, elle accédera à la référence enfant et aura toutes les fonctions de l'élément enfant).Maintenant, le composant enfant, tel que théoriquement conçu précédemment, ressemblera à:
Voici le code source -
Hope vous aidera!
la source
Si vous faites cela simplement parce que vous voulez que l'enfant fournisse un trait réutilisable à ses parents, alors vous pourriez envisager de le faire en utilisant des accessoires de rendu à la place.
Cette technique bouleverse la structure. L'
Child
enveloppe maintenant le parent, donc je l'ai renommé ci-AlertTrait
dessous. J'ai gardé le nomParent
de continuité, même si ce n'est plus vraiment un parent maintenant.Dans ce cas, le AlertTrait fournit un ou plusieurs traits qu'il transmet comme accessoires à n'importe quel composant qui lui a été donné dans son
renderComponent
accessoire.Le parent reçoit
doAlert
comme accessoire et peut l'appeler en cas de besoin.(Pour plus de clarté, j'ai appelé l'hélice
renderComponent
dans l'exemple ci-dessus. Mais dans les documents React liés ci-dessus, ils l'appellent justerender
.)Le composant Trait peut restituer des éléments entourant le parent, dans sa fonction de rendu, mais il ne rend rien à l'intérieur du parent. En fait, il pourrait rendre des choses à l'intérieur du parent, s'il passait un autre accessoire (par exemple
renderChild
) au parent, que le parent pourrait ensuite utiliser lors de sa méthode de rendu.C'est quelque peu différent de ce que le PO a demandé, mais certaines personnes pourraient se retrouver ici (comme nous l'avons fait) parce qu'elles voulaient créer un trait réutilisable et pensaient qu'un composant enfant était un bon moyen de le faire.
la source
this.clickChild = click
mais vos chronomètres multiples passeraient plusieurs fonctions, vous devriez donc tous les stocker:this.watchRestartFuncs[watchId] = restartWatch
Vous pouvez y parvenir facilement de cette manière
Pas-
À partir du composant enfant, accédez à cette variable à l'aide d'accessoires et exécutez la méthode souhaitée en ayant une condition if.
la source
J'utilise le
useEffect
crochet pour surmonter le mal de tête de faire tout cela alors maintenant je transmets une variable à l'enfant comme ceci:la source
Je n'ai été satisfait d'aucune des solutions présentées ici. Il existe en fait une solution très simple qui peut être faite en utilisant du Javascript pur sans compter sur une fonctionnalité React autre que l'objet d'accessoires de base - et cela vous donne l'avantage de communiquer dans les deux sens (parent -> enfant, enfant -> parent). Vous devez passer un objet du composant parent au composant enfant. Cet objet est ce que j'appelle une "référence bidirectionnelle" ou biRef pour faire court. Fondamentalement, l'objet contient une référence aux méthodes du parent que le parent souhaite exposer. Et le composant enfant attache des méthodes à l'objet que le parent peut appeler. Quelque chose comme ça:
L'autre avantage de cette solution est que vous pouvez ajouter beaucoup plus de fonctions dans le parent et l'enfant tout en les passant du parent à l'enfant en utilisant une seule propriété.
Une amélioration par rapport au code ci-dessus consiste à ne pas ajouter les fonctions parent et enfant directement à l'objet biRef mais plutôt aux sous-membres. Les fonctions parents doivent être ajoutées à un membre appelé "parent" tandis que les fonctions enfants doivent être ajoutées à un membre appelé "enfant".
En plaçant les fonctions parent et enfant dans des membres distincts de l'objet biRef, vous aurez une séparation nette entre les deux et vous verrez facilement celles qui appartiennent au parent ou à l'enfant. Cela aide également à empêcher un composant enfant d'écraser accidentellement une fonction parent si la même fonction apparaît dans les deux.
Une dernière chose est que si vous remarquez, le composant parent crée l'objet biRef avec var tandis que le composant enfant y accède via l'objet props. Il peut être tentant de ne pas définir l'objet biRef dans le parent et d'y accéder depuis son parent via son propre paramètre d'accessoires (ce qui pourrait être le cas dans une hiérarchie d'éléments d'interface utilisateur). Cela est risqué car l'enfant peut penser qu'une fonction qu'il appelle sur le parent appartient au parent alors qu'elle pourrait en fait appartenir à un grand-parent. Il n'y a rien de mal à cela tant que vous en êtes conscient. Sauf si vous avez une raison de prendre en charge une hiérarchie au-delà d'une relation parent / enfant, il est préférable de créer le biRef dans votre composant parent.
la source
Vous pouvez faire une inversion d'héritage (recherchez-la ici: https://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e ). De cette façon, vous avez accès à l'instance du composant que vous emballeriez (vous pourrez ainsi accéder à ses fonctions)
la source
Je pense que la façon la plus simple d'appeler des méthodes consiste à définir une requête sur le composant enfant. Ensuite, dès que l'enfant gère la demande, il appelle une méthode de rappel pour réinitialiser la demande.
Le mécanisme de réinitialisation est nécessaire pour pouvoir envoyer la même demande plusieurs fois de suite.
Dans le composant parent
Dans la méthode de rendu du parent:
Le parent a besoin de 2 méthodes pour communiquer avec son enfant dans 2 directions.
Dans le composant enfant
L'enfant met à jour son état interne, copiant la demande des accessoires.
Enfin, il gère la demande et envoie la réinitialisation au parent:
la source
Une autre façon de déclencher une fonction enfant à partir du parent consiste à utiliser la
componentDidUpdate
fonction dans le composant enfant. Je passe un accessoiretriggerChildFunc
de Parent à Enfant, ce qui est initialement le casnull
. La valeur se transforme en fonction lorsque l'utilisateur clique sur le bouton et que l'enfant remarque qu'il changecomponentDidUpdate
et appelle sa propre fonction interne.Étant donné que prop
triggerChildFunc
change une fonction, nous obtenons également un rappel au parent. Si Parent n'a pas besoin de savoir quand la fonction est appelée, la valeurtriggerChildFunc
peut par exemple changer denull
à à latrue
place.CodePen: https://codepen.io/calsal/pen/NWPxbJv?editors=1010
la source
Voici ma démo: https://stackblitz.com/edit/react-dgz1ee?file=styles.css
J'utilise
useEffect
pour appeler les méthodes du composant enfants. J'ai essayé avec,Proxy and Setter_Getter
mais de loin, celauseEffect
semble être le moyen le plus pratique d'appeler une méthode enfant à partir du parent. Pour l'utiliser,Proxy and Setter_Getter
il semble qu'il y ait une subtilité à surmonter d'abord, car l'élément rendu en premier est un élément objectLike à travers laref.current return => <div/>
spécificité de. ConcernantuseEffect
, vous pouvez également tirer parti de cette approche pour définir l'état du parent en fonction de ce que vous voulez faire avec les enfants.Dans le lien de la démo que j'ai fourni, vous trouverez mon code ReactJS complet avec mes ébauches à l'intérieur afin que vous puissiez apprécier le flux de travail de ma solution.
Ici, je vous fournis mon extrait de ReactJS avec le code correspondant uniquement. :
la source
Nous sommes satisfaits d'un crochet personnalisé que nous appelons
useCounterKey
. Il configure simplement une counterKey, ou une clé qui compte à partir de zéro. La fonction qu'elle renvoie réinitialise la clé (c'est-à-dire incrémente). (Je pense que c'est la façon la plus idiomatique dans React de réinitialiser un composant - il suffit de bousculer la clé.)Cependant, ce hook fonctionne également dans toutes les situations où vous souhaitez envoyer un message unique au client pour faire quelque chose. Par exemple, nous l'utilisons pour concentrer un contrôle chez l'enfant sur un certain événement parent - il se concentre automatiquement à chaque fois que la clé est mise à jour. (Si plus d'accessoires sont nécessaires, ils peuvent être définis avant de réinitialiser la clé afin qu'ils soient disponibles lorsque l'événement se produit.)
Cette méthode a un peu une courbe d'apprentissage b / c ce n'est pas aussi simple qu'un gestionnaire d'événements typique, mais cela semble la façon la plus idiomatique de gérer cela dans React que nous avons trouvé (puisque les clés fonctionnent déjà de cette façon). Def ouvert aux commentaires sur cette méthode, mais cela fonctionne bien!
Exemples d'utilisation:
( Nous remercions Kent Dodds pour le concept counterKey .)
la source
Voici un bug? à surveiller: je suis d'accord avec la solution de rossipedia utilisant forwardRef, useRef, useImperativeHandle
Il y a des informations erronées en ligne qui disent que les références ne peuvent être créées qu'à partir de composants React Class, mais vous pouvez en effet utiliser les composants de fonction si vous utilisez les crochets susmentionnés. Une note, les crochets n'ont fonctionné pour moi qu'après avoir modifié le fichier pour ne pas utiliser withRouter () lors de l'exportation du composant. C'est à dire un changement de
être à la place
Avec le recul, withRouter () n'est de toute façon pas nécessaire pour un tel composant, mais généralement cela ne fait rien de mal à l'avoir. Mon cas d'utilisation est que j'ai créé un composant pour créer une table pour gérer l'affichage et la modification des valeurs de configuration, et je voulais pouvoir dire à ce composant enfant de réinitialiser ses valeurs d'état chaque fois que le bouton de réinitialisation du formulaire parent était enfoncé. UseRef () n'obtiendrait pas correctement le ref ou ref.current (continuait à devenir nul) jusqu'à ce que je supprime withRouter () du fichier contenant mon composant enfant TableConfig
la source