J'ai la structure suivante:
FormEditor
- contient plusieurs FieldEditor
FieldEditor
- modifie un champ du formulaire et enregistre diverses valeurs à ce sujet dans son état
Lorsqu'un bouton est cliqué dans FormEditor, je veux pouvoir collecter des informations sur les champs de tous les FieldEditor
composants, des informations qui sont dans leur état, et les avoir toutes dans FormEditor.
J'ai envisagé de stocker les informations sur les champs en dehors de FieldEditor
l'état et de les mettre à FormEditor
la place. Cependant, cela nécessiterait FormEditor
d'écouter chacun de ses FieldEditor
composants lorsqu'ils changent et de stocker leurs informations dans son état.
Je ne peux pas simplement accéder à l'état des enfants à la place? Est-ce que c'est idéal?
la source
FieldEditor
s séparément, sauvegarder leur état dans unFormEditor
bon son. Si tel est le cas, vosFieldEditor
instances seront rendues en fonction de cellesprops
passées par leur éditeur de formulaire, et non par leurstate
. Un moyen plus complexe mais flexible serait de créer un sérialiseur qui passe par tous les enfants de conteneur et trouve toutes lesFormEditor
instances parmi eux et les sérialise en un objet JSON. L'objet JSON peut être éventuellement imbriqué (plusieurs niveaux) en fonction des niveaux d'imbrication des instances dans l'éditeur de formulaire.Réponses:
Si vous avez déjà un gestionnaire onChange pour les FieldEditors individuels, je ne vois pas pourquoi vous ne pouvez pas simplement déplacer l'état vers le composant FormEditor et simplement transmettre un rappel à partir de là aux FieldEditors qui mettront à jour l'état parent. Cela me semble être une façon plus réactive de le faire.
Quelque chose dans le sens de cela peut-être:
Original - version pré-crochets:
Afficher l'extrait de code
la source
myAPI.SaveStuff(this.state);
. Si vous développez un peu plus, je peux peut-être vous donner une meilleure réponse :)Avant d'entrer dans les détails sur la façon dont vous pouvez accéder à l'état d'un composant enfant, assurez-vous de lire la réponse de Markus-ipse concernant une meilleure solution pour gérer ce scénario particulier.
Si vous souhaitez en effet accéder à l'état des enfants d'un composant, vous pouvez affecter une propriété appelée
ref
à chaque enfant. Il existe maintenant deux façons d'implémenter des références: UtilisationReact.createRef()
et références de rappel.En utilisant
React.createRef()
C'est actuellement la manière recommandée d'utiliser les références à partir de React 16.3 (Voir la documentation pour plus d'informations). Si vous utilisez une version antérieure, consultez ci-dessous les références de rappel.
Vous devrez créer une nouvelle référence dans le constructeur de votre composant parent, puis l'affecter à un enfant via l'
ref
attribut.Pour accéder à ce type de référence, vous devrez utiliser:
Cela renverra une instance du composant monté afin que vous puissiez ensuite l'utiliser
currentFieldEditor1.state
pour accéder à l'état.Juste une petite note pour dire que si vous utilisez ces références sur un nœud DOM au lieu d'un composant (par exemple
<div ref={this.divRef} />
), alorsthis.divRef.current
retournera l'élément DOM sous-jacent au lieu d'une instance de composant.Références de rappel
Cette propriété prend une fonction de rappel qui reçoit une référence au composant attaché. Ce rappel est exécuté immédiatement après le montage ou le démontage du composant.
Par exemple:
Dans ces exemples, la référence est stockée sur le composant parent. Pour appeler ce composant dans votre code, vous pouvez utiliser:
puis utilisez
this.fieldEditor1.state
pour obtenir l'état.Une chose à noter, assurez-vous que votre composant enfant est restitué avant d'essayer d'y accéder ^ _ ^
Comme ci-dessus, si vous utilisez ces références sur un nœud DOM au lieu d'un composant (par exemple
<div ref={(divRef) => {this.myDiv = divRef;}} />
), alorsthis.divRef
retournera l'élément DOM sous-jacent au lieu d'une instance de composant.Plus d'informations
Si vous souhaitez en savoir plus sur la propriété ref de React, consultez cette page sur Facebook.
Assurez-vous de lire la section « Ne pas abuser des références » qui dit que vous ne devez pas utiliser l'enfant
state
pour «faire bouger les choses».J'espère que cela aide ^ _ ^
Modifier: Ajout d'une
React.createRef()
méthode pour créer des références. Suppression du code ES5.la source
this.refs.yourComponentNameHere
. Je l'ai trouvé utile pour changer d'état via des fonctions. Exemple:this.refs.textInputField.clearInput();
props
etstate
. Cependant, ils ne doivent pas être votre abstraction de référence pour le flux de données via votre application. Par défaut, utilisez le flux de données réactif et enregistrez lesref
s pour les cas d'utilisation qui sont intrinsèquement non réactifs.connected
composant Redux ?C'est 2020 et beaucoup d'entre vous viendront ici à la recherche d'une solution similaire mais avec des crochets (ils sont super!) Et avec les dernières approches en termes de propreté et de syntaxe du code.
Ainsi que les réponses précédentes l'avaient indiqué, la meilleure approche pour ce type de problème est de maintenir l'état en dehors de la composante enfant
fieldEditor
. Vous pouvez le faire de plusieurs manières.Le plus "complexe" concerne le contexte global (état) auquel les parents et les enfants peuvent accéder et modifier. C'est une excellente solution lorsque les composants sont très profonds dans la hiérarchie de l'arborescence et qu'il est donc coûteux d'envoyer des accessoires à chaque niveau.
Dans ce cas, je pense que cela n'en vaut pas la peine, et une approche plus simple nous apportera les résultats que nous voulons, en utilisant simplement les puissants
React.useState()
.Approche avec le crochet React.useState (), beaucoup plus simple qu'avec les composants Class
Comme nous l'avons dit, nous allons gérer les changements et stocker les données de notre composant enfant
fieldEditor
dans notre parentfieldForm
. Pour ce faire, nous enverrons une référence à la fonction qui traitera et appliquera les modifications à l'fieldForm
état, vous pouvez le faire avec:Notez que
React.useState({})
retournera un tableau avec la position 0 étant la valeur spécifiée lors de l'appel (objet vide dans ce cas), et la position 1 étant la référence à la fonction qui modifie la valeur.Maintenant, avec le composant enfant
FieldEditor
, vous n'avez même pas besoin de créer une fonction avec une instruction return, une constante maigre avec une fonction flèche fera l'affaire!Aaaaand nous avons terminé, rien de plus, avec seulement ces deux composants fonctionnels de slime, nous avons notre objectif final "accéder" à notre
FieldEditor
valeur enfant et le montrer dans notre parent.Vous pouvez vérifier la réponse acceptée il y a 5 ans et voir comment Hooks a rendu le code React plus léger (par beaucoup!).
J'espère que ma réponse vous aidera à en apprendre davantage et à mieux comprendre les crochets, et si vous voulez vérifier un exemple de travail ici, c'est ici .
la source
Vous pouvez maintenant accéder à l'état de InputField qui est l'enfant de FormEditor.
Fondamentalement, chaque fois qu'il y a un changement dans l'état du champ de saisie (enfant), nous obtenons la valeur de l'objet événement, puis transmettons cette valeur au parent où l'état du parent est défini.
Au clic sur le bouton, nous imprimons simplement l'état des champs de saisie.
Le point clé ici est que nous utilisons les accessoires pour obtenir l'id / valeur du champ d'entrée et également pour appeler les fonctions qui sont définies comme attributs sur le champ d'entrée pendant que nous générons les champs d'entrée enfants réutilisables.
la source
Comme indiqué dans les réponses précédentes, essayez de déplacer l'état vers un composant supérieur et de modifier l'état via des rappels passés à ses enfants.
Si vous avez vraiment besoin d'accéder à un état enfant déclaré en tant que composant fonctionnel (hooks), vous pouvez déclarer une référence dans le composant parent, puis la transmettre en tant qu'attribut ref à l'enfant, mais vous devez utiliser React.forwardRef puis le hook useImperativeHandle pour déclarer une fonction que vous pouvez appeler dans le composant parent.
Jetez un œil à l'exemple suivant:
Ensuite, vous devriez pouvoir obtenir myState dans le composant Parent en appelant:
myRef.current.getMyState();
la source