Je viens de commencer avec ReactJS et je suis un peu coincé sur un problème que j'ai.
Mon application est essentiellement une liste avec des filtres et un bouton pour changer la mise en page. En ce moment , j'utilise trois composantes: <list />
, < Filters />
et <TopBar />
, maintenant évidemment quand je change les paramètres dans < Filters />
je veux déclencher une méthode <list />
pour mettre à jour mon avis.
Comment puis-je faire interagir ces 3 composants entre eux, ou ai-je besoin d'une sorte de modèle de données global sur lequel je peux simplement apporter des modifications?
javascript
reactjs
woutr_be
la source
la source
Réponses:
La meilleure approche dépend de la façon dont vous prévoyez d'organiser ces composants. Quelques exemples de scénarios qui vous viennent à l'esprit en ce moment:
<Filters />
est un composant enfant de<List />
<Filters />
et<List />
sont les enfants d'un composant parent<Filters />
et<List />
vivent entièrement dans des composants racine séparés.Il peut y avoir d'autres scénarios auxquels je ne pense pas. Si le vôtre ne rentre pas dans ces limites, faites-le moi savoir. Voici quelques exemples très approximatifs de la façon dont j'ai géré les deux premiers scénarios:
Scénario 1
Vous pouvez passer un gestionnaire de
<List />
à<Filters />
, qui pourrait ensuite être appelé sur l'onChange
événement pour filtrer la liste avec la valeur actuelle.JSFiddle pour # 1 →
Scénario # 2
Similaire au scénario n ° 1, mais le composant parent sera celui qui transmettra la fonction de gestionnaire à
<Filters />
, et passera la liste filtrée à<List />
. J'aime mieux cette méthode car elle dissocie le<List />
du<Filters />
.JSFiddle pour # 2 →
Scénario # 3
Lorsque les composants ne peuvent pas communiquer entre une sorte de relation parent-enfant, la documentation recommande de configurer un système d'événements global .
la source
updateFilter
à<Filters />
et un tableau quantitems
à<List />
. Vous pouvez utiliser ces composants enfants chez d'autres parents avec des comportements différents, ensemble ou en solo. Par exemple, si vous souhaitez afficher une liste dynamique mais n'avez pas besoin de filtrage.Il existe plusieurs façons de faire communiquer les composants. Certains peuvent être adaptés à votre cas d'utilisation. Voici une liste de certains que j'ai trouvé utile de connaître.
Réagir
Communication directe parents / enfants
Ici, le composant enfant appellera un rappel fourni par le parent avec une valeur, et le parent pourra obtenir la valeur fournie par les enfants du parent.
Si vous créez une fonctionnalité / page de votre application, il est préférable qu'un seul parent gère les rappels / l'état (également appelé
container
ousmart component
) et que tous les enfants soient apatrides, ne signalant que les choses au parent. De cette façon, vous pouvez facilement «partager» l'état du parent à tout enfant qui en a besoin.Le contexte
React Context permet de maintenir l'état à la racine de la hiérarchie de vos composants et de pouvoir injecter facilement cet état dans des composants imbriqués très profondément, sans avoir à passer des accessoires à tous les composants intermédiaires.
Jusqu'à présent, le contexte était une fonctionnalité expérimentale, mais une nouvelle API est disponible dans React 16.3.
Le consommateur utilise le modèle de fonction render prop / children
Consultez cet article de blog pour plus de détails.
Avant React 16.3, je recommanderais d'utiliser react-broadcast qui offre une API assez similaire et d'utiliser l'ancienne API de contexte.
Portails
Utilisez un portail lorsque vous souhaitez garder 2 composants proches l'un de l'autre pour les faire communiquer avec des fonctions simples, comme dans un parent / enfant normal, mais vous ne voulez pas que ces 2 composants aient une relation parent / enfant dans le DOM, car des contraintes visuelles / CSS qu'elle implique (comme le z-index, l'opacité ...).
Dans ce cas, vous pouvez utiliser un "portail". Il existe différentes bibliothèques React utilisant des portails , généralement utilisés pour les modaux , les popups, les info-bulles ...
Considérer ce qui suit:
Pourrait produire le DOM suivant lors du rendu à l'intérieur
reactAppContainer
:Plus de détails ici
Machines à sous
Vous définissez un emplacement quelque part, puis vous remplissez l'emplacement à partir d'un autre endroit de votre arborescence de rendu.
C'est un peu similaire aux portails, sauf que le contenu rempli sera rendu dans un emplacement que vous définissez, tandis que les portails rendent généralement un nouveau nœud dom (souvent un enfant de document.body)
Vérifier la bibliothèque React-Slot-Fill
Bus d'événement
Comme indiqué dans la documentation React :
Il existe de nombreuses choses que vous pouvez utiliser pour configurer un bus d'événements. Vous pouvez simplement créer un tableau d'auditeurs, et lors de la publication de l'événement, tous les écouteurs recevraient l'événement. Ou vous pouvez utiliser quelque chose comme EventEmitter ou PostalJs
Flux
Flux est essentiellement un bus d'événements, sauf que les récepteurs d'événements sont des magasins. Ceci est similaire au système de bus d'événements de base, sauf que l'état est géré en dehors de React
L'implémentation de Flux d'origine ressemble à une tentative de faire du sourcing d'événements de manière hacky.
Redux est pour moi l'implémentation de Flux qui est la plus proche de l'événementiel, et bénéficie de nombreux avantages de l'événementiel comme la possibilité de voyager dans le temps. Il n'est pas strictement lié à React et peut également être utilisé avec d'autres bibliothèques de vues fonctionnelles.
Le tutoriel vidéo Redux d'Egghead est vraiment sympa et explique comment cela fonctionne en interne (c'est vraiment simple).
Curseurs
Les curseurs proviennent de ClojureScript / Om et sont largement utilisés dans les projets React. Ils permettent de gérer l'état en dehors de React et permettent à plusieurs composants d'accéder en lecture / écriture à la même partie de l'état, sans avoir besoin de connaître quoi que ce soit sur l'arborescence des composants.
De nombreuses implémentations existent, y compris ImmutableJS , React-cursors et Omniscient
Edit 2016 : il semble que les gens conviennent que les curseurs fonctionnent bien pour les petites applications, mais il ne s'adapte pas bien aux applications complexes. Om Next n'a plus de curseurs (alors que c'est Om qui a introduit le concept initialement)
Architecture d'orme
L' architecture Elm est une architecture proposée pour être utilisée par le langage Elm . Même si Elm n'est pas ReactJS, l'architecture Elm peut également être réalisée dans React.
Dan Abramov, l'auteur de Redux, a réalisé une implémentation de l'architecture Elm en utilisant React.
Redux et Elm sont vraiment excellents et ont tendance à renforcer les concepts de sourcing d'événements sur le frontend, permettant à la fois le débogage dans le temps, l'annulation / la restauration, la relecture ...
La principale différence entre Redux et Elm est que Elm a tendance à être beaucoup plus strict sur la gestion de l'État. Dans Elm, vous ne pouvez pas avoir d'état de composant local ou de montage / démontage de crochets et toutes les modifications DOM doivent être déclenchées par des changements d'état globaux. L'architecture Elm propose une approche évolutive qui permet de gérer TOUS les états à l'intérieur d'un seul objet immuable, tandis que Redux propose une approche qui vous invite à gérer la PLUPART des états dans un seul objet immuable.
Alors que le modèle conceptuel d'Elm est très élégant et que l'architecture permet de bien évoluer sur de grandes applications, il peut en pratique être difficile ou impliquer plus de passe-partout pour réaliser des tâches simples comme donner le focus à une entrée après l'avoir montée, ou l'intégrer à une bibliothèque existante avec une interface impérative (ie plugin JQuery). Problème connexe .
De plus, l'architecture Elm implique davantage de code passe-partout. Ce n'est pas verbeux ou compliqué à écrire, mais je pense que l'architecture Elm est plus adaptée aux langages typés statiquement.
FRP
Des bibliothèques comme RxJS, BaconJS ou Kefir peuvent être utilisées pour produire des flux FRP pour gérer la communication entre les composants.
Vous pouvez essayer par exemple Rx-React
Je pense que l'utilisation de ces bibliothèques est assez similaire à l'utilisation de ce que le langage ELM offre avec des signaux .
Le framework CycleJS n'utilise pas ReactJS mais utilise vdom . Il partage beaucoup de similitudes avec l'architecture Elm (mais est plus facile à utiliser dans la vie réelle car il autorise les hooks vdom) et il utilise largement les RxJ au lieu des fonctions, et peut être une bonne source d'inspiration si vous souhaitez utiliser FRP avec Réagir. Les vidéos CycleJs Egghead sont agréables à comprendre comment cela fonctionne.
CSP
Les CSP (Communicating Sequential Processes) sont actuellement populaires (principalement à cause de Go / goroutines et core.async / ClojureScript) mais vous pouvez également les utiliser en javascript avec JS-CSP .
James Long a réalisé une vidéo expliquant comment il peut être utilisé avec React.
Sagas
Une saga est un concept de backend issu du monde DDD / EventSourcing / CQRS, également appelé "gestionnaire de processus". Il est popularisé par le projet redux-saga , principalement en remplacement de redux-thunk pour la gestion des effets secondaires (c'est-à-dire les appels API, etc.). La plupart des gens pensent actuellement qu'il ne sert que pour les effets secondaires, mais qu'il s'agit en fait davantage de découplage des composants.
C'est plus un complément à une architecture Flux (ou Redux) qu'un système de communication totalement nouveau, car la saga émet des actions Flux à la fin. L'idée est que si vous avez widget1 et widget2 et que vous souhaitez les découpler, vous ne pouvez pas déclencher d'action ciblant widget2 depuis widget1. Donc, vous ne faites que widget1 déclencher des actions qui se ciblent, et la saga est un "processus d'arrière-plan" qui écoute les actions widget1, et peut envoyer des actions qui ciblent widget2. La saga est le point de couplage entre les 2 widgets mais les widgets restent découplés.
Si vous êtes intéressé, regardez ma réponse ici
Conclusion
Si vous souhaitez voir un exemple de la même petite application utilisant ces différents styles, vérifiez les branches de ce référentiel .
Je ne sais pas quelle est la meilleure option à long terme mais j'aime vraiment à quoi Flux ressemble à un événementiel.
Si vous ne connaissez pas les concepts de l'événementiel, jetez un œil à ce blog très pédagogique: tourner la base de données à l'envers avec apache Samza , c'est une lecture incontournable pour comprendre pourquoi Flux est sympa (mais cela pourrait aussi s'appliquer à FRP )
Je pense que la communauté convient que l'implémentation la plus prometteuse de Flux est Redux , qui permettra progressivement une expérience de développeur très productive grâce au rechargement à chaud. Le livecoding impressionnant de la vidéo Inventing on Principle de Bret Victor est possible!
la source
OK, il y a peu de façons de le faire, mais je veux exclusivement me concentrer sur l'utilisation du magasin en utilisant Redux qui vous facilite la vie dans ces situations plutôt que de vous donner une solution rapide uniquement dans ce cas, l'utilisation de React pur finira par gâcher dans une très grande application et la communication entre les composants devient de plus en plus difficile à mesure que l'application se développe ...
Alors, que fait Redux pour vous?
Redux est comme le stockage local dans votre application qui peut être utilisé chaque fois que vous avez besoin de données à utiliser à différents endroits de votre application ...
Fondamentalement, l'idée de Redux provient du flux à l'origine, mais avec quelques changements fondamentaux, y compris le concept d'avoir une seule source de vérité en créant un seul magasin ...
Regardez le graphique ci-dessous pour voir quelques différences entre Flux et Redux ...
Envisagez d'appliquer Redux dans votre application dès le départ si votre application a besoin d'une communication entre les composants ...
La lecture de ces mots de la documentation Redux pourrait également être utile pour commencer:
la source
datepicker
(en tant que composant) et que ce composant peut être chargé à partir de plusieurs composants vivant sur la même page, alors comment ledatepicker
composant saura-t-il quelle action envoyer à redux? C'est l'essence du problème, reliant une action dans un composant à un autre et NON à aucun autre composant . (prenez en considération que ledatepicker
lui-même est un composant profond, profond au sein du composant modal lui-même)redux
ce que vous pouvez stocker, mais COMMENT transmettre l'action en profondeur à ce qui doit la déclencher. Comment un composant profond sait-il exactement ce qui doit être déclenché? car dans l'exemple, j'ai donné un composant général qui devrait se déclencher sur un réducteur spécifique, selon le scénario, il pourrait donc être un réducteur différent car un modal datepicker peut être utilisé pour n'importe quel composant.C'est ainsi que j'ai géré cela.
Disons que vous avez un <select> pour le mois et un <select> pour le jour . Le nombre de jours dépend du mois sélectionné.
Les deux listes appartiennent à un troisième objet, le panneau de gauche. Les deux <select> sont également des enfants du leftPanel <div>
C'est un jeu avec les rappels et les gestionnaires dans le composant LeftPanel .
Pour le tester, copiez simplement le code dans deux fichiers séparés et exécutez index.html . Sélectionnez ensuite un mois et voyez comment le nombre de jours change.
dates.js
Et le code HTML pour exécuter le composant de panneau gauche index.html
la source
J'ai vu que la question est déjà répondue, mais si vous souhaitez en savoir plus, il existe au total 3 cas de communication entre composants :
la source
En étendant la réponse de @MichaelLaCroix lorsqu'un scénario est que les composants ne peuvent pas communiquer entre toute sorte de relation parent-enfant, la documentation recommande de configurer un système d'événement global.
Dans le cas de
<Filters />
et<TopBar />
n'ayant aucune des relations ci-dessus, un émetteur global simple pourrait être utilisé comme ceci:componentDidMount
- Abonnez-vous à l'événementcomponentWillUnmount
- Se désinscrire de l'événementCode React.js et EventSystem
EventSystem.js
NotificationComponent.js
la source
Il y a une telle possibilité même si ce n'est pas une relation Parent - Enfant - et c'est Flux. Il y a une assez bonne implémentation (pour moi personnellement) pour celle appelée Alt.JS (avec Alt-Container).
Par exemple, vous pouvez avoir une barre latérale qui dépend de ce qui est défini dans les détails du composant. Le composant Sidebar est connecté à SidebarActions et SidebarStore, tandis que Details correspond à DetailsActions et DetailsStore.
Vous pouvez alors utiliser AltContainer comme ça
Qui garderait les magasins (enfin je pourrais utiliser "store" au lieu de "stores" prop). Maintenant, {this.props.content} PEUT ÊTRE Détails selon l'itinéraire. Disons que / Details nous redirige vers cette vue. Les détails auraient par exemple une case à cocher qui changerait l'élément de la barre latérale de X à Y s'il était coché.
Techniquement, il n'y a pas de relation entre eux et il serait difficile de se passer de flux. MAIS AVEC CELA, c'est plutôt facile.
Passons maintenant à DetailsActions. Nous allons y créer
et DétailsStore
Et maintenant, c'est l'endroit où la magie commence.
Comme vous pouvez le voir, il y a bindListener à SidebarActions.ComponentStatusChanged qui sera utilisé SI setSiteComponent sera utilisé.
maintenant dans SidebarActions
Nous avons une telle chose. Il enverra cet objet sur appel. Et il sera appelé si setSiteComponent en magasin sera utilisé (que vous pouvez utiliser dans le composant par exemple pendant onChange on Button ou autre)
Maintenant, dans SidebarStore, nous aurons
Maintenant, ici, vous pouvez voir qu'il attendra DetailsStore. Qu'est-ce que ça veut dire? plus ou moins, cela signifie que cette méthode doit attendre la mise à jour de DetailsStoreto avant de pouvoir se mettre à jour.
tl; dr One Store écoute les méthodes d'un magasin et déclenchera une action à partir de l'action du composant, qui mettra à jour son propre magasin.
J'espère que cela peut vous aider d'une manière ou d'une autre.
la source
Si vous souhaitez explorer les options de communication entre les composants et avoir l'impression que cela devient de plus en plus difficile, vous pouvez envisager d'adopter un bon modèle de conception: Flux .
Il s'agit simplement d'une collection de règles qui définit la façon dont vous stockez et modifiez l'état à l'échelle de l'application et utilisez cet état pour rendre les composants.
Il existe de nombreuses implémentations de Flux, et l'implémentation officielle de Facebook en fait partie. Bien qu'il soit considéré comme celui qui contient le plus de code passe-partout, il est plus facile à comprendre car la plupart des choses sont explicites.
Certaines des autres alternatives sont flummox fluxxor fluxible et redux .
la source
Une fois, j'étais là où vous êtes en ce moment, en tant que débutant, vous vous sentez parfois hors de propos sur la manière de réagir. Je vais essayer de m'attaquer de la même manière que j'y pense en ce moment.
Les États sont la pierre angulaire de la communication
Habituellement, cela se résume à la façon dont vous modifiez les états de ce composant dans votre cas, vous indiquez trois composants.
<List />
: Qui affichera probablement une liste d'éléments en fonction d'un filtre<Filters />
: Options de filtrage qui modifieront vos données.<TopBar />
: Liste d'options.Pour orchestrer toute cette interaction, vous allez avoir besoin d'un composant plus élevé appelons-le App, qui transmettra des actions et des données à chacun de ces composants afin par exemple de ressembler à ceci
Ainsi, quand
setFilter
est appelé, cela affectera le FilterItem et restituera les deux composants ;. Dans le cas où ce n'est pas tout à fait clair, je vous ai fait un exemple avec une case à cocher que vous pouvez archiver dans un seul fichier:la source
Le code suivant m'aide à configurer la communication entre deux frères et sœurs. La configuration est effectuée dans leur parent lors des appels de render () et componentDidMount (). Il est basé sur https://reactjs.org/docs/refs-and-the-dom.html J'espère que cela vous aidera.
la source
Curieusement, personne n'a mentionné
mobx
. L'idée est similaire àredux
. Si j'ai une donnée à laquelle plusieurs composants sont abonnés, je peux utiliser ces données pour piloter plusieurs composants.la source