ReactJS Deux composants communiquant

Je viens juste de commencer avec ReactJS et je suis un peu coincé sur un problème que j’ai.

Mon application est essentiellement une liste de filtres et un bouton pour modifier la mise en page. En ce moment, j’utilise trois composants: , et , maintenant évidemment quand je change les parameters dans je veux déclencher une méthode dans pour mettre à jour mon vue.

Comment puis-je faire en sorte que ces 3 composants interagissent les uns avec les autres ou ai-je besoin d’un modèle de données global dans lequel je peux simplement apporter des modifications?

La meilleure approche dépend de la façon dont vous prévoyez d’organiser ces composants. Quelques exemples de scénarios qui viennent à l’esprit maintenant:

  1. est un composant enfant de
  2. Les deux et sont des enfants d’un composant parent
  3. et vivent entièrement dans des composants racine distincts.

Il y a peut-être d’autres scénarios auxquels je ne pense pas. Si le vôtre ne correspond pas à ceux-ci, alors 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 à , qui pourrait ensuite être appelé sur l’événement onChange pour filtrer la liste avec la valeur actuelle.

JSFiddle pour # 1 →

 /** @jsx React.DOM */ var Filters = React.createClass({ handleFilterChange: function() { var value = this.refs.filterInput.getDOMNode().value; this.props.updateFilter(value); }, render: function() { return ; } }); var List = React.createClass({ getInitialState: function() { return { listItems: ['Chicago', 'New York', 'Tokyo', 'London', 'San Francisco', 'Amsterdam', 'Hong Kong'], nameFilter: '' }; }, handleFilterUpdate: function(filterValue) { this.setState({ nameFilter: filterValue }); }, render: function() { var displayedItems = this.state.listItems.filter(function(item) { var match = item.toLowerCase().indexOf(this.state.nameFilter.toLowerCase()); return (match !== -1); }.bind(this)); var content; if (displayedItems.length > 0) { var items = displayedItems.map(function(item) { return 
  • {item}
  • ; }); content =
      {items}
    } else { content =

    No items matching this filter

    ; } return (

    Results

    {content}
    ); } }); React.renderComponent(, document.body);

    Scénario n ° 2

    Semblable au scénario n ° 1, mais le composant parent sera celui transmettant la fonction de gestionnaire à et transmettra la liste filtrée à . J’aime mieux cette méthode car elle dissocie le du .

    JSFiddle pour # 2 →

     /** @jsx React.DOM */ var Filters = React.createClass({ handleFilterChange: function() { var value = this.refs.filterInput.getDOMNode().value; this.props.updateFilter(value); }, render: function() { return ; } }); var List = React.createClass({ render: function() { var content; if (this.props.items.length > 0) { var items = this.props.items.map(function(item) { return 
  • {item}
  • ; }); content =
      {items}
    } else { content =

    No items matching this filter

    ; } return (

    Results

    {content}
    ); } }); var ListContainer = React.createClass({ getInitialState: function() { return { listItems: ['Chicago', 'New York', 'Tokyo', 'London', 'San Francisco', 'Amsterdam', 'Hong Kong'], nameFilter: '' }; }, handleFilterUpdate: function(filterValue) { this.setState({ nameFilter: filterValue }); }, render: function() { var displayedItems = this.state.listItems.filter(function(item) { var match = item.toLowerCase().indexOf(this.state.nameFilter.toLowerCase()); return (match !== -1); }.bind(this)); return (
    ); } }); React.renderComponent(, document.body);

    Scénario n ° 3

    Lorsque les composants ne peuvent communiquer entre aucune relation parent-enfant, la documentation recommande de configurer un système d’événements global .

    Il existe plusieurs façons de faire communiquer les composants. Certains peuvent être adaptés à vos besoins. Voici une liste de certains que j’ai trouvé utile de savoir.

    Réagir

    Communication directe parent / enfant

     const Child = ({fromChildToParentCallback}) => ( 
    fromChildToParentCallback(42)}> Click me
    ); class Parent extends React.Component { receiveChildValue = (value) => { console.log("Parent received value from child: " + value); // value is 42 }; render() { return ( ) } }

    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 / état (également appelé container ou smart component ) et que tous les enfants soient sans état, ne signalant que les choses au parent. De cette façon, vous pouvez facilement “partager” l’état du parent avec tout enfant qui en a besoin.


    Le contexte

    React Context permet de maintenir l’état à la racine de votre hiérarchie de composants et d’être capable d’injecter cet état facilement dans des composants très nesteds, sans avoir à transmettre 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.

     const AppContext = React.createContext(null) class App extends React.Component { render() { return (  
    ... ...
    ) } }; const SomeDeeplyNestedComponent = () => ( {({language}) =>
    App language is currently {language}
    }
    );

    Le consommateur utilise le motif de fonction prop / children de rendu

    Consultez cet article pour plus de détails.

    Avant React 16.3, je vous recommande 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 les uns des autres 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. des contraintes visuelles / CSS qu’il implique (comme z-index, opacité …).

    Dans ce cas, vous pouvez utiliser un “portail”. Il existe différentes bibliothèques de réactions utilisant des portails , généralement utilisées pour les modaux , les popups, les info-bulles …

    Considérer ce qui suit:

     
    a content
    b content

    Pourrait produire le DOM suivant lors du rendu dans reactAppContainer :

      
    a content
    b content

    Plus de détails ici


    Bus événementiel

    Comme indiqué dans la documentation de React:

    Pour la communication entre deux composants sans relation parent-enfant, vous pouvez configurer votre propre système d’événements global. Abonnez-vous aux événements de componentDidMount (), désabonnez-vous de componentWillUnmount () et appelez setState () lorsque vous recevez un événement.

    Il y a beaucoup de choses que vous pouvez utiliser pour configurer un bus d’événement. Vous pouvez simplement créer un tableau d’écouteurs et, lors de la publication d’événements, tous les écouteurs recevront l’événement. Ou vous pouvez utiliser quelque chose comme EventEmitter ou PostalJs


    Flux

    Flux est essentiellement un bus d’événement, 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 recherche d’événements de manière pirate.

    Redux est pour moi l’implémentation de Flux la plus proche de l’approvisionnement par événement, un avantage pour de nombreux avantages en matière de recherche d’événements, comme la possibilité de voyager dans le temps. Il n’est pas ssortingctement lié à React et peut également être utilisé avec d’autres bibliothèques de vues fonctionnelles.

    Le didacticiel vidéo d’ Egghead sur Redux est vraiment sympa et explique comment cela fonctionne en interne (c’est vraiment simple).


    Des 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’avoir access en lecture / écriture à la même partie de l’état, sans avoir besoin de connaître 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 correctement pour les applications plus petites, mais que les applications complexes ne sont pas très évolutives. Om Next n’a plus de curseur (alors que c’est Om qui a introduit le concept initialement)


    L’architecture des ormes

    L’ architecture Elm est une architecture proposée pour être utilisée par la langue 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 tous deux excellents et ont tendance à renforcer les concepts d’identification des événements sur le front-end, à la fois autorisant le débogage, l’annulation / la répétition, la relecture …

    La principale différence entre Redux et Elm est qu’Elm a tendance à être beaucoup plus ssortingct sur la gestion de l’état. Dans Elm, vous ne pouvez pas avoir d’état de composant local ni de crochets de assembly / déassembly et toutes les modifications DOM doivent être déclenchées par des modifications d’état globales. L’architecture d’Elm propose une approche évolutive qui permet de gérer TOUT l’état dans un seul object immuable, tandis que Redux propose une approche qui vous invite à gérer le plus grand nombre d’états dans un seul object immuable.

    Bien que le modèle conceptuel d’Elm soit très élégant et que l’architecture lui permette de bien évoluer sur de grandes applications, il peut être difficile ou plus complexe d’accomplir des tâches simples telles que l’intégration dans une bibliothèque existante. avec une interface impérative (ie plugin JQuery). Problème lié

    En outre, l’architecture d’Elm implique davantage de code. Ce n’est pas si compliqué à écrire, mais je pense que l’architecture Elm est plus adaptée aux langages statiquement typés.


    FRP

    Des bibliothèques telles que RxJS, BaconJS ou Kefir peuvent être utilisées pour produire des stream FRP afin de 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 propose le langage ELM avec les 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 permet des hooks vdom) et il utilise beaucoup RxJ au lieu de fonctions, et peut être une bonne source d’inspiration si vous souhaitez utiliser FRP avec Réagir. Les vidéos de CycleJs Egghead sont agréables à comprendre.


    CSP

    CSP (Communicating Sequential Processes) sont actuellement populaires (principalement grâce à 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 utiliser React.

    Sagas

    Une saga est un concept backend issu du monde DDD / EventSourcing / CQRS, également appelé “gestionnaire de processus”. Il est popularisé par le projet redux-saga , principalement en remplacement du redux-thunk pour gérer les effets secondaires (appels API, etc.). Actuellement, la plupart des gens pensent que cela ne concerne que les effets secondaires, mais en réalité, il s’agit plus de découpler les composants.

    C’est plus un compliment à 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 un widget1 et un widget2, et que vous souhaitez qu’ils soient découplés, vous ne pouvez pas déclencher le widget2 de ciblage d’action à partir du widget1. Ainsi, vous ne faites que déclencher par le widget1 des actions qui lui-même ciblent, et la saga est un “processus d’arrière-plan” qui écoute les actions du widget1 et peut envoyer des actions au widget2 cible. La saga est le sharepoint couplage entre les 2 widgets mais les widgets restnt découplés.

    Si vous êtes intéressé, regardez ma réponse ici


    Conclusion

    Si vous voulez voir un exemple de la même petite application utilisant ces différents styles, vérifiez les twigs de ce référentiel .

    Je ne sais pas quelle est la meilleure option à long terme, mais j’aime beaucoup la façon dont Flux ressemble à un approvisionnement par événement.

    Si vous ne connaissez pas les concepts d’éventail, jetez un coup d’œil à ce blog très pédagogique: Donner un coup de pouce à la firebase database avec apache Samza est une lecture incontournable pour comprendre pourquoi Flux est intéressant (mais aussi pour FRP) )

    Je pense que la communauté est d’accord pour dire que l’implémentation la plus prometteuse de Flux est Redux , qui permettra progressivement une expérience de développement très productive grâce au rechargement à chaud. Un livecoding impressionnant, la vidéo Inventing on Princ de Bret Victor est possible!

    C’est comme ça que j’ai géré ça.
    Disons que vous avez un

    Les deux listes appartiennent à un troisième object, le panneau de gauche. Les deux

    Pour le tester, copiez simplement le code dans deux fichiers séparés et exécutez le fichier index.html . Sélectionnez ensuite un mois et voyez comment le nombre de jours change.

    dates.js

      /** @jsx React.DOM */ var monthsLength = [0,31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; var MONTHS_ARR = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]; var DayNumber = React.createClass({ render: function() { return (  ); } }); var DaysList = React.createClass({ getInitialState: function() { return {numOfDays: 30}; }, handleMonthUpdate: function(newMonthix) { this.state.numOfDays = monthsLength[newMonthix]; console.log("Setting days to " + monthsLength[newMonthix] + " month = " + newMonthix); this.forceUpdate(); }, handleDaySelection: function(evt) { this.props.dateHandler(evt.target.value); }, componentDidMount: function() { this.props.readyCallback(this.handleMonthUpdate) }, render: function() { var dayNodes = []; for (i = 1; i < = this.state.numOfDays; i++) { dayNodes = dayNodes.concat([]); } return (  ); } }); var Month = React.createClass({ render: function() { return (  ); } }); var MonthsList = React.createClass({ handleUpdate: function(evt) { console.log("Local handler:" + this.props.id + " VAL= " + evt.target.value); this.props.dateHandler(evt.target.value); return false; }, render: function() { var monthIx = 0; var monthNodes = this.props.data.map(function (month) { monthIx++; return (  ); }); return (  ); } }); var LeftPanel = React.createClass({ dayRefresh: function(newMonth) { // Nothing - will be replaced }, daysReady: function(refreshCallback) { console.log("Regisering days list"); this.dayRefresh = refreshCallback; }, handleMonthChange: function(monthIx) { console.log("New month"); this.dayRefresh(monthIx); }, handleDayChange: function(dayIx) { console.log("New DAY: " + dayIx); }, render: function() { return( 
    ); } }); React.renderComponent( , document.getElementById('leftPanel') );

    Et le HTML pour exécuter le composant du panneau de gauche index.html

     < !DOCTYPE html>   Dates        

    J’ai vu que la question a déjà reçu une réponse, mais si vous souhaitez en savoir plus, il existe au total 3 cas de communication entre les composants :

    • Cas 1: Communication de parent à enfant
    • Cas 2: communication enfant à parent
    • Cas 3: Composants non liés (tout composant à un composant) communication

    En étendant la réponse de @MichaelLaCroix quand 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énements global.

    Dans le cas de et n’ont aucune des relations ci-dessus, un émetteur global simple pourrait être utilisé comme ceci:

    componentDidMount – S’abonner à un événement

    componentWillUnmount – Se désinscrire de l’événement

    React.js et le code EventSystem

    EventSystem.js

     class EventSystem{ constructor() { this.queue = {}; this.maxNamespaceSize = 50; } publish(/** namespace **/ /** arguments **/) { if(arguments.length < 1) { throw "Invalid namespace to publish"; } var namespace = arguments[0]; var queue = this.queue[namespace]; if (typeof queue === 'undefined' || queue.length < 1) { console.log('did not find queue for %s', namespace); return false; } var valueArgs = Array.prototype.slice.call(arguments); valueArgs.shift(); // remove namespace value from value args queue.forEach(function(callback) { callback.apply(null, valueArgs); }); return true; } subscribe(/** namespace **/ /** callback **/) { const namespace = arguments[0]; if(!namespace) throw "Invalid namespace"; const callback = arguments[arguments.length - 1]; if(typeof callback !== 'function') throw "Invalid callback method"; if (typeof this.queue[namespace] === 'undefined') { this.queue[namespace] = []; } const queue = this.queue[namespace]; if(queue.length === this.maxNamespaceSize) { console.warn('Shifting first element in queue: `%s` since it reached max namespace queue count : %d', namespace, this.maxNamespaceSize); queue.shift(); } // Check if this callback already exists for this namespace for(var i = 0; i < queue.length; i++) { if(queue[i] === callback) { throw ("The exact same callback exists on this namespace: " + namespace); } } this.queue[namespace].push(callback); return [namespace, callback]; } unsubscribe(/** array or topic, method **/) { let namespace; let callback; if(arguments.length === 1) { let arg = arguments[0]; if(!arg || !Array.isArray(arg)) throw "Unsubscribe argument must be an array"; namespace = arg[0]; callback = arg[1]; } else if(arguments.length === 2) { namespace = arguments[0]; callback = arguments[1]; } if(!namespace || typeof callback !== 'function') throw "Namespace must exist or callback must be a function"; const queue = this.queue[namespace]; if(queue) { for(var i = 0; i < queue.length; i++) { if(queue[i] === callback) { queue.splice(i, 1); // only unique callbacks can be pushed to same namespace queue return; } } } } setNamespaceSize(size) { if(!this.isNumber(size)) throw "Queue size must be a number"; this.maxNamespaceSize = size; return true; } isNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n); } } 

    NotificationComponent.js

     class NotificationComponent extends React.Component { getInitialState() { return { // optional. see alternative below subscriber: null }; } errorHandler() { const topic = arguments[0]; const label = arguments[1]; console.log('Topic %s label %s', topic, label); } componentDidMount() { var subscriber = EventSystem.subscribe('error.http', this.errorHandler); this.state.subscriber = subscriber; } componentWillUnmount() { EventSystem.unsubscribe('error.http', this.errorHandler); // alternatively // EventSystem.unsubscribe(this.state.subscriber); } render() { } } 

    OK, il y a peu de façons de le faire, mais je veux exclusivement me concentrer sur l’utilisation de la boutique en utilisant Redux, ce qui vous simplifie la vie plutôt que de vous donner une solution rapide. la vraie application et la communication entre les composants deviennent de plus en plus difficiles à mesure que l’application se développe …

    Alors, que fait Redux pour vous?

    Redux est comme un stockage local dans votre application qui peut être utilisé chaque fois que vous avez besoin d’une donnée à utiliser à différents endroits de votre application …

    Fondamentalement, l’idée de Redux vient de stream à l’origine, mais avec quelques changements fondamentaux, y compris le concept d’avoir une source de vérité en créant un seul magasin …

    Regardez le graphique ci-dessous pour voir quelques différences entre Flux et Redux

    Redux et Flux

    Pensez à appliquer Redux dans votre application dès le début si votre application nécessite la communication entre les composants …

    Lire également ces mots de la documentation Redux pourrait être utile pour commencer avec:

    Comme les exigences pour les applications JavaScript à page unique sont de plus en plus complexes, notre code doit gérer plus d’états que jamais . Cet état peut inclure des réponses de serveur et des données mises en cache, ainsi que des données créées localement qui n’ont pas encore été conservées sur le serveur. L’état de l’interface utilisateur devient également de plus en plus complexe, car nous devons gérer les itinéraires actifs, les tabs sélectionnés, les filateurs, les contrôles de pagination, etc.

    La gestion de cet état en constante évolution est difficile. Si un modèle peut mettre à jour un autre modèle, une vue peut mettre à jour un modèle, qui met à jour un autre modèle, ce qui peut entraîner la mise à jour d’une autre vue. À un moment donné, vous ne comprenez plus ce qui se passe dans votre application, car vous avez perdu le contrôle du moment, de la raison et de son état. Lorsqu’un système est opaque et non déterministe, il est difficile de reproduire des bogues ou d’append de nouvelles fonctionnalités.

    Comme si cela ne suffisait pas, considérez que les nouvelles exigences deviennent courantes dans le développement de produits frontaux. En tant que développeurs, nous sums censés gérer les mises à jour optimistes, le rendu côté serveur, l’extraction des données avant d’effectuer les transitions d’itinéraires, etc. Nous nous trouvons en train de gérer une complexité que nous n’avons jamais eu à traiter auparavant et nous posons inévitablement la question suivante: est-il temps d’abandonner? La réponse est non.

    Cette complexité est difficile à gérer car nous mélangeons deux concepts très difficiles à comprendre pour l’esprit humain: la mutation et l’asynchronicité. Je les appelle Mentos et Coca. Les deux peuvent être formidables en termes de séparation, mais ensemble, ils créent un désordre. Les bibliothèques comme React tentent de résoudre ce problème dans la couche de visualisation en supprimant les manipulations asynchrones et directes. Cependant, la gestion de l’état de vos données est laissée à vous. C’est là que Redux entre.

    Suivant les étapes de Flux, CQRS et Event Sourcing , Redux tente de rendre les mutations d’état prévisibles en imposant certaines ressortingctions sur la manière et le moment où les mises à jour peuvent se produire . Ces ressortingctions sont reflétées dans les trois principes de Redux.

    Il y a une telle possibilité même s’ils ne sont pas parent-enfant – et c’est Flux. Il y a une très 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. La barre latérale des composants est connectée à SidebarActions et SidebarStore, tandis que Détails est DétailsActions et DétailsStore.

    Vous pourriez utiliser alors AltContainer comme ça

        {this.props.content} 

    Ce 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 / Détails 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 ce serait difficile à faire sans stream. MAIS AVEC QUE c’est plutôt facile.

    Passons maintenant aux détails. Nous y créerons

     class SiteActions { constructor() { this.generateActions( 'setSiteComponentStore' ); } setSiteComponent(value) { this.dispatch({value: value}); } } 

    et détailsStore

     class SiteStore { constructor() { this.siteComponents = { Prop: true }; this.bindListeners({ setSiteComponent: SidebarActions.COMPONENT_STATUS_CHANGED }) } setSiteComponent(data) { this.siteComponents.Prop = data.value; } } 

    Et maintenant, c’est l’endroit où la magie commence.

    Comme vous pouvez le voir, il existe bindListener à SidebarActions.ComponentStatusChanged qui sera utilisé SI setSiteComponent sera utilisé.

    maintenant dans SidebarActions

      componentStatusChanged(value){ this.dispatch({value: value}); } 

    Nous avons une telle chose. Il enverra cet object sur appel. Et on l’appellera si setSiteComponent in store sera utilisé (que vous pouvez utiliser dans component par exemple pendant onChange on Button ou autre)

    Maintenant, dans SidebarStore, nous aurons

      constructor() { this.structures = []; this.bindListeners({ componentStatusChanged: SidebarActions.COMPONENT_STATUS_CHANGED }) } componentStatusChanged(data) { this.waitFor(DetailsStore); _.findWhere(this.structures[0].elem, {title: 'Example'}).enabled = data.value; } 

    Maintenant, vous pouvez voir qu’il attendra DetailsStore. Qu’est-ce que ça veut dire? cela signifie plus ou moins que cette méthode doit attendre la mise à jour de DetailsStor 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 composant, qui mettra à jour son propre magasin.

    J’espère que cela peut vous aider.

    Si vous souhaitez explorer les options de communication entre les composants et avoir l’impression qu’il devient de plus en plus difficile, vous pouvez envisager d’adopter un bon modèle de conception: Flux .

    Il s’agit simplement d’un ensemble de règles qui définissent la manière dont vous stockez et modifiez l’état général de l’application et utilisez cet état pour rendre les composants.

    Il y a beaucoup d’implémentations de Flux, et l’implémentation officielle de Facebook en est une. Bien qu’il soit considéré comme contenant le code le plus standard, il est plus facile à comprendre car la plupart des choses sont explicites.

    Parmi les autres alternatives, citons le streamant et le streamable .

    J’étais une fois 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’y attaquer de la même façon que je le pense maintenant.

    Les États sont la pierre angular de la communication

    Habituellement, la manière dont vous modifiez les états de ce composant dans votre cas est de déterminer trois composants.

    : qui affichera probablement une liste d’éléments en fonction d’un filtre : options de filtre qui modifieront vos données. : liste des options.

    Pour orchestrer toute cette interaction, vous allez avoir besoin d’un composant plus élevé, appelons-le App, qui transmettra les actions et les données à chacun de ces composants.

     

    Ainsi, lorsque setFilter est appelé, cela affectera le filterItem et restituera les deux composants. Au cas où ce ne serait pas tout à fait clair, je vous ai donné un exemple avec une case à cocher que vous pouvez archiver dans un seul fichier:

     import React, {Component} from 'react'; import {render} from 'react-dom'; const Person = ({person, setForDelete}) => ( 
    {person.name}
    ); class PeopleList extends Component { render() { return(
    {this.props.people.map((person, i) => { return ; })}
    Delete Selected Records
    ); } } // end class class App extends React.Component { constructor(props) { super(props) this.state = {people:[{id:1, name:'Cesar', checked:false},{id:2, name:'Jose', checked:false},{id:3, name:'Marbel', checked:false}]} } deleteRecords() { const people = this.state.people.filter(p => !p.checked); this.setState({people}); } setForDelete(person) { const checked = !person.checked; const people = this.state.people.map((p)=>{ if(p.id === person.id) return {name:person.name, checked}; return p; }); this.setState({people}); } render () { return ; } } render(, document.getElementById('app'));

    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 render () et componentDidMount (). Il est basé sur https://reactjs.org/docs/refs-and-the-dom.html J’espère que ça aide.

     class App extends React.Component { private _navigationPanel: NavigationPanel; private _mapPanel: MapPanel; constructor() { super(); this.state = {}; } // `componentDidMount()` is called by ReactJS after `render()` componentDidMount() { // Pass _mapPanel to _navigationPanel // It will allow _navigationPanel to call _mapPanel directly this._navigationPanel.setMapPanel(this._mapPanel); } render() { return ( 
    // `ref=` helps to get reference to a child during rendering { this._navigationPanel = child; }} /> { this._mapPanel = child; }} />
    ); } }