ReactJS Due componenti che comunicano

Ho appena iniziato con ReactJS e sono un po ‘bloccato su un problema che ho.

La mia applicazione è essenzialmente una lista con filtri e un pulsante per cambiare il layout. Al momento sto usando tre componenti: , e , ora ovviamente quando cambio le impostazioni in Voglio triggersre un metodo in per aggiornare il mio vista.

Come posso rendere questi 3 componenti interagenti tra loro, o ho bisogno di una sorta di modello di dati globale in cui posso semplicemente apportare modifiche?

L’approccio migliore dipenderà dal modo in cui pianifichi di organizzare tali componenti. Alcuni scenari di esempio che vengono in mente in questo momento:

  1. è un componente figlio di
  2. Sia che sono figli di un componente padre
  3. e vivono interamente in componenti root separati.

Potrebbero esserci altri scenari a cui non penso. Se il tuo non rientra in questi, fammelo sapere. Ecco alcuni esempi molto approssimativi di come ho gestito i primi due scenari:

Scenario 1

È ansible passare un gestore da a , che potrebbe quindi essere chiamato sull’evento onChange per filtrare l’elenco con il valore corrente.

JSFiddle per # 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);

    Scenario n. 2

    Simile allo scenario n. 1, ma il componente genitore sarà quello che trasmette la funzione di gestione a e passerà l’elenco filtrato a . Mi piace questo metodo perché disaccoppia dai .

    JSFiddle per # 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);

    Scenario n. 3

    Quando i componenti non possono comunicare tra qualsiasi tipo di relazione genitore-figlio, la documentazione consiglia di impostare un sistema di eventi globale .

    Esistono diversi modi per comunicare i componenti. Alcuni possono essere adatti al tuo caso. Ecco una lista di alcuni che ho trovato utile sapere.

    Reagire

    Comunicazione diretta genitore / figlio

     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 ( ) } }

    Qui il componente figlio chiamerà un callback fornito dal genitore con un valore, e il genitore sarà in grado di ottenere il valore fornito dai figli nel genitore.

    Se crei una funzione / pagina della tua app, è meglio avere un solo genitore che gestisca lo stato dei callback / (chiamato anche container o smart component ) e che tutti i child siano stateless, riportando solo le cose al genitore. In questo modo puoi facilmente “condividere” lo stato del genitore con qualsiasi bambino che ne abbia bisogno.


    Contesto

    React Context consente di mantenere lo stato nella radice della gerarchia dei componenti, ed essere in grado di iniettare questo stato facilmente in componenti molto profondamente annidati, senza il fastidio di dover tramandare oggetti di scena a tutti i componenti intermedi.

    Fino ad ora, il contesto era una funzionalità sperimentale, ma una nuova API è disponibile in React 16.3.

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

    Il consumatore sta usando il modello di funzione rendering / bambini

    Controlla questo post sul blog per maggiori dettagli.

    Prima di React 16.3, raccomanderei l’uso di react-broadcast che offre API abbastanza simili e utilizzare l’ex API di contesto.


    portali

    Utilizzare un portale quando si desidera mantenere 2 componenti ravvicinati per farli comunicare con funzioni semplici, come nel normale genitore / figlio, ma non si vuole che questi 2 componenti abbiano una relazione genitore / figlio nel DOM, perché dei vincoli visivi / CSS che implica (come z-index, opacity …).

    In questo caso puoi usare un “portale”. Ci sono diverse librerie di reactjs usando i portali , solitamente usati per modali , popup, tooltip …

    Considera quanto segue:

     
    a content
    b content

    Potrebbe produrre il seguente DOM durante il rendering all’interno di reactAppContainer :

      
    a content
    b content

    Maggiori dettagli qui


    Bus degli eventi

    Come indicato nella documentazione di React:

    Per la comunicazione tra due componenti che non hanno una relazione genitore-figlio, è ansible impostare il proprio sistema di eventi globale. Iscriviti agli eventi in componentDidMount (), annulla l’iscrizione a componentWillUnmount () e chiama setState () quando ricevi un evento.

    Ci sono molte cose che puoi usare per configurare un bus eventi. Puoi semplicemente creare una serie di ascoltatori e sulla pubblicazione degli eventi, tutti gli ascoltatori riceveranno l’evento. Oppure puoi usare qualcosa come EventEmitter o PostalJs


    Flusso

    Flux è fondamentalmente un bus eventi, ad eccezione dei ricevitori degli eventi. Questo è simile al sistema di bus di eventi di base tranne che lo stato è gestito al di fuori di React

    L’implementazione di Flux originale sembra un tentativo di fare il sourcing di eventi in modo hacky.

    Redux è per me l’implementazione di Flux che è la più vicina all’evento-sourcing, un vantaggio molti dei vantaggi dell’outsourcing come la capacità di viaggiare nel tempo. Non è strettamente collegato a React e può anche essere utilizzato con altre librerie di viste funzionali.

    Il video tutorial di Egghead Redux è davvero carino e spiega come funziona internamente (è davvero semplice).


    Cursori

    I cursori provengono da ClojureScript / Om e sono ampiamente utilizzati nei progetti React. Consentono di gestire lo stato all’esterno di React e consentono a più componenti di accedere in lettura / scrittura alla stessa parte dello stato, senza la necessità di sapere nulla sull’albero dei componenti.

    Esistono molte implementazioni, tra cui ImmutableJS , React-cursors e Onnisciente

    Modifica 2016 : sembra che le persone concordino che i cursori funzionino bene per le app più piccole, ma non si adatta bene alle app complesse. Om Next non ha più cursori (mentre Om ha introdotto inizialmente il concetto)


    Architettura olmo

    L’ architettura di Elm è un’architettura proposta per essere utilizzata dalla lingua Elm . Anche se Elm non è ReactJS, l’architettura Elm può essere eseguita anche in React.

    Dan Abramov, l’autore di Redux, ha realizzato un’implementazione dell’architettura di Elm usando React.

    Sia Redux che Elm sono davvero fantastici e tendono a potenziare i concetti di sourcing degli eventi sul frontend, consentendo entrambi il debug del time-travel, annulla / ripristina, replay …

    La principale differenza tra Redux ed Elm è che gli Elm tendono ad essere molto più rigidi sulla gestione dello stato. In Elm non è ansible avere lo stato del componente locale o gli hook di assembly / sassembly e tutte le modifiche del DOM devono essere triggerste dalle modifiche dello stato globale. L’architettura di Elm propone un approccio scalabile che consente di gestire TUTTO lo stato all’interno di un singolo object immutabile, mentre Redux propone un approccio che invita a gestire MOST dello stato in un singolo object immutabile.

    Mentre il modello concettuale di Elm è molto elegante e l’architettura consente di adattarsi bene alle app di grandi dimensioni, in pratica può essere difficile o richiedere più standard per ottenere semplici compiti come dare un input a un input dopo averlo montato o integrarlo con una libreria esistente con un’interfaccia imperativa (es. plugin JQuery). Problema correlato

    Inoltre, l’architettura di Elm richiede più codice per il codice. Non è verboso o complicato da scrivere, ma penso che l’architettura di Elm sia più adatta ai linguaggi tipizzati staticamente.


    FRP

    Librerie come RxJS, BaconJS o Kefir possono essere utilizzate per produrre flussi FRP per gestire le comunicazioni tra i componenti.

    Puoi provare ad esempio Rx-React

    Penso che l’uso di queste librerie sia abbastanza simile all’utilizzo di ciò che il linguaggio ELM offre con i segnali .

    Il framework CycleJS non utilizza ReactJS ma utilizza vdom . Condivide molte somiglianze con l’architettura Elm (ma è più facile da usare nella vita reale perché consente gli hook di vdom) e usa RxJ estesamente invece di funzioni, e può essere una buona fonte di ispirazione se si desidera utilizzare FRP con Reagire. I video di CycleJs Egghead sono piacevoli per capire come funziona.


    CSP

    I CSP (Communicating Sequential Processes) sono attualmente popolari (principalmente a causa di Go / goroutines e core.async / ClojureScript) ma è ansible utilizzarli anche in javascript con JS-CSP .

    James Long ha realizzato un video che spiega come può essere usato con React.

    Sagas

    Una saga è un concetto di backend che viene dal mondo DDD / EventSourcing / CQRS, chiamato anche “process manager”. È reso popolare dal progetto redux-saga , principalmente come rimpiazzo a redux-thunk per la gestione degli effetti collaterali (ad esempio chiamate API, ecc.). La maggior parte delle persone attualmente ritiene che si tratti solo di servizi per effetti collaterali, ma in realtà si tratta più di disaccoppiamento dei componenti.

    È più un complimento per un’architettura Flux (o Redux) che un sistema di comunicazione totalmente nuovo, perché la saga emette azioni Flux alla fine. L’idea è che se hai widget1 e widget2 e vuoi che siano disaccoppiati, non puoi triggersre il widget di targeting azione2 da widget1. Quindi fai widget1 solo azioni di fuoco che hanno come bersaglio se stesso, e la saga è un “processo in background” che ascolta le azioni del widget1 e può inviare azioni che hanno come target widget2. La saga è il punto di accoppiamento tra i 2 widget, ma i widget rimangono disaccoppiati.

    Se sei interessato dai un’occhiata alla mia risposta qui


    Conclusione

    Se vuoi vedere un esempio della stessa piccola app che usa questi stili diversi, controlla i rami di questo repository .

    Non so quale sia l’opzione migliore a lungo termine, ma mi piace molto il modo in cui Flux appare come l’event-sourcing.

    Se non conoscete i concetti di sourcing di eventi , date un’occhiata a questo blog molto pedagogico: girando il database con Apache Samza , è una lettura obbligata per capire perché Flux è bello (ma potrebbe applicarsi anche a FRP )

    Penso che la community sia d’accordo sul fatto che l’implementazione di Flux più promettente sia Redux , che consentirà progressivamente un’esperienza di sviluppo molto produttiva grazie al ricaricamento a caldo. Impressionante livecoding ala Bret Victor’s Inventing on Principle video è ansible!

    Questo è il modo in cui ho gestito questo.
    Supponiamo che tu abbia un

    Entrambi gli elenchi sono di proprietà di un terzo object, il pannello di sinistra. Entrambi

    Per testarlo, copia il codice in due file separati ed esegui index.html . Quindi selezionare un mese e vedere come cambia il numero di giorni.

    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') );

    E l’HTML per l’esecuzione del componente del pannello sinistro index.html

        Dates        

    Ho visto che la domanda ha già una risposta, ma se vuoi saperne di più dettagli, ci sono un totale di 3 casi di comunicazione tra componenti :

    • Caso 1: comunicazione da padre a figlio
    • Caso 2: comunicazione da bambino a genitore
    • Caso 3: comunicazione dei componenti non correlati (qualsiasi componente a qualsiasi componente)

    Estendendo la risposta di @MichaelLaCroix quando uno scenario è che i componenti non possono comunicare tra qualsiasi tipo di relazione genitore-figlio, la documentazione consiglia di impostare un sistema di eventi globale.

    Nel caso di e non abbiamo nessuna delle relazioni precedenti, un semplice emettitore globale potrebbe essere usato in questo modo:

    componentDidMount – Iscriviti all’evento

    componentWillUnmount – Annulla l’iscrizione all’evento

    Codice React.js ed 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, ci sono alcuni modi per farlo, ma voglio concentrarmi esclusivamente sull’utilizzo di store usando Redux che rende la vita molto più facile per queste situazioni piuttosto che darti una soluzione rapida solo per questo caso, usando React puro finirai per incasinare la vera grande applicazione e la comunicazione tra i componenti diventano sempre più difficili man mano che l’applicazione cresce …

    Quindi cosa fa Redux per te?

    Redux è come l’archiviazione locale nella tua applicazione che può essere utilizzata ogni volta che è necessario che i dati vengano utilizzati in diversi punti dell’applicazione …

    Fondamentalmente l’idea di Redux proviene dal stream originariamente, ma con alcuni cambiamenti fondamentali tra cui il concetto di avere una fonte di verità creando solo un negozio …

    Guarda il grafico qui sotto per vedere alcune differenze tra Flux e Redux

    Redux e Flux

    Prendi in considerazione l’applicazione di Redux nella tua applicazione dall’inizio se la tua applicazione richiede la comunicazione tra i componenti …

    Anche leggere queste parole da Redux Documentation potrebbe essere utile per iniziare:

    Poiché i requisiti per le applicazioni a pagina singola JavaScript sono diventati sempre più complicati, il nostro codice deve gestire più stato che mai . Questo stato può includere risposte del server e dati memorizzati nella cache, nonché dati creati localmente che non sono ancora stati mantenuti sul server. Anche lo stato dell’interfaccia utente sta diventando sempre più complesso, in quanto è necessario gestire i percorsi attivi, le tabs selezionate, i pennini, i controlli di impaginazione e così via.

    Gestire questo stato in continua evoluzione è difficile. Se un modello può aggiornare un altro modello, una vista può aggiornare un modello, che aggiorna un altro modello e questo, a sua volta, potrebbe causare l’aggiornamento di un’altra vista. Ad un certo punto, non capisci più cosa succede nella tua app perché hai perso il controllo sul quando, perché e come del suo stato. Quando un sistema è opaco e non deterministico, è difficile riprodurre bug o aggiungere nuove funzionalità.

    Come se ciò non fosse abbastanza negativo, considera i nuovi requisiti diventare comuni nello sviluppo del prodotto front-end. Come sviluppatori, ci aspettiamo di gestire aggiornamenti ottimistici, rendering lato server, recupero dei dati prima di eseguire transizioni di route e così via. Ci troviamo a cercare di gestire una complessità che non abbiamo mai dovuto affrontare prima, e inevitabilmente ci poniamo la domanda: è ora di arrendersi? La risposta è no.

    Questa complessità è difficile da gestire poiché stiamo mescolando due concetti che sono molto difficili da ragionare per la mente umana: mutazione e asincronismo. Li chiamo Mentos e Coca-Cola. Entrambi possono essere grandi nella separazione, ma insieme creano un casino. Le librerie come React tentano di risolvere questo problema nel livello vista rimuovendo sia l’asincronia che la manipolazione diretta del DOM. Tuttavia, la gestione dello stato dei tuoi dati è a tua discrezione. È qui che entra Redux.

    Seguendo i passaggi di Flux, CQRS e Event Sourcing , Redux tenta di rendere prevedibili le mutazioni di stato imponendo alcune restrizioni su come e quando possono verificarsi gli aggiornamenti . Queste restrizioni si riflettono nei tre principi di Redux.

    C’è una tale possibilità anche se non sono Parent – Child – e questo è Flux. C’è un’implementazione abbastanza buona (per me personalmente) per quella che si chiama Alt.JS (con Alt-Container).

    Ad esempio, puoi disporre di Sidebar che dipende da ciò che è impostato in Dettagli componente. La sidebar dei componenti è collegata con SidebarActions e SidebarStore, mentre Details è DetailsActions e DetailsStore.

    Potresti usare quindi AltContainer in questo modo

        {this.props.content} 

    Che manterrebbe i negozi (beh, potrei usare “store” invece di “store” prop). Ora, {this.props.content} PU CAN ESSERE Dettagli a seconda del percorso. Diciamo che / Dettagli ci reindirizza a quella vista. I dettagli avrebbero ad esempio una casella di controllo che cambierebbe l’elemento della barra laterale da X a Y se verrebbe controllato.

    Tecnicamente non c’è alcuna relazione tra loro e sarebbe difficile fare a meno del stream. MA CON QUELLO è piuttosto facile.

    Ora passiamo a DetailsActions. Creeremo lì

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

    e DetailsStore

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

    E ora, questo è il posto dove inizia la magia.

    Come puoi vedere c’è bindListener a SidebarActions.ComponentStatusChanged che verrà utilizzato se verrà utilizzato setSiteComponent.

    ora in SidebarActions

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

    Abbiamo una cosa del genere. Spedirà quell’object su chiamata. E verrà chiamato se verrà utilizzato setSiteComponent in negozio (che è ansible utilizzare nel componente ad esempio durante onChange on Button o qualsiasi altra cosa)

    Ora in SidebarStore avremo

      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; } 

    Ora qui puoi vedere che attenderà DetailsStore. Cosa significa? più o meno significa che questo metodo deve attendere l’aggiornamento di DetailsStoreto prima che possa aggiornarsi.

    tl; dr One Store ascolta i metodi in un negozio e attiverà un’azione dall’azione componente, che aggiornerà il proprio negozio.

    Spero possa aiutarti in qualche modo.

    Se vuoi esplorare le opzioni di comunicazione tra componenti e senti come sta diventando sempre più difficile, allora potresti prendere in considerazione l’adozione di un buon modello di design: Flux .

    È semplicemente una raccolta di regole che definisce il modo in cui memorizzi e muti lo stato a livello di applicazione e utilizzi quello stato per eseguire il rendering dei componenti.

    Ci sono molte implementazioni di Flux e l’implementazione ufficiale di Facebook è una di queste. Anche se è considerato quello che contiene la maggior parte del codice boilerplate, ma è più facile da capire poiché la maggior parte delle cose sono esplicite.

    Alcune delle altre alternative sono fluxxor fluxxor fluxible e redux .

    Una volta ero dove sei adesso, come principiante a volte ti senti fuori posto su come reactjs in questo modo. Cercherò di affrontare allo stesso modo in cui ci penso adesso.

    Gli Stati sono la pietra angular per la comunicazione

    Di solito si tratta del modo in cui si alterano gli stati di questo componente nel caso in cui si indicano tre componenti.

    : che probabilmente mostrerà un elenco di elementi a seconda del filtro : opzioni di filtro che altereranno i tuoi dati. : elenco di opzioni.

    Per orchestrare tutte queste interazioni avrai bisogno di un componente più alto chiamiamolo App, che trasmetterà azioni e dati a ciascuno di questi componenti, così ad esempio può assomigliare a questo

     

    Quindi, quando viene chiamato setFilter questo avrà effetto su filteredItem e renderà nuovamente entrambi i componenti ;. Nel caso in cui questo non sia completamente chiaro ti ho fatto un esempio con checkbox che puoi verificare in un singolo file:

     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'));

    Il seguente codice mi aiuta a impostare la comunicazione tra due fratelli. L’installazione viene eseguita in genitore durante le chiamate render () e componentDidMount (). È basato su https://reactjs.org/docs/refs-and-the-dom.html Spero che aiuti.

     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; }} />
    ); } }