Come aggiornare lo stato del genitore in React?

La mia struttura ha il seguente aspetto:

Component 1 - |- Component 2 - - |- Component 4 - - - |- Component 5 Component 3 

Il componente 3 dovrebbe visualizzare alcuni dati a seconda dello stato del componente 5. Poiché i puntelli sono immutabili, non posso semplicemente salvare lo stato nel componente 1 e inoltrarlo, giusto? E sì, ho letto su Redux, ma non voglio usarlo. Spero che sia ansible risolverlo solo con la reazione. Ho sbagliato?

    Per la comunicazione figlio-genitore si dovrebbe passare una funzione impostando lo stato da genitore a figlio, come in questo caso

     class Parent extends React.Component { constructor(props) { super(props) this.handler = this.handler.bind(this) } handler(e) { e.preventDefault() this.setState({ someVar: someValue }) } render() { return  } } class Child extends React.Component { render() { return  

    Ho trovato la seguente soluzione di lavoro per passare l’argomento della funzione Click da bambino al componente principale:

    Versione con passaggio di un metodo ()

     //ChildB component class ChildB extends React.Component { render() { var handleToUpdate = this.props.handleToUpdate; return (
    ) } } //ParentA component class ParentA extends React.Component { constructor(props) { super(props); var handleToUpdate = this.handleToUpdate.bind(this); var arg1 = ''; } handleToUpdate(someArg){ alert('We pass argument from Child to Parent: ' + someArg); this.setState({arg1:someArg}); } render() { var handleToUpdate = this.handleToUpdate; return (
    ) } } if(document.querySelector("#demo")){ ReactDOM.render( , document.querySelector("#demo") ); }

    Guarda JSFIDDLE

    Versione con passaggio di una funzione di freccia

     //ChildB component class ChildB extends React.Component { render() { var handleToUpdate = this.props.handleToUpdate; return (
    ) } } //ParentA component class ParentA extends React.Component { constructor(props) { super(props); } handleToUpdate = (someArg) => { alert('We pass argument from Child to Parent: ' + someArg); } render() { return (
    ) } } if(document.querySelector("#demo")){ ReactDOM.render( , document.querySelector("#demo") ); }

    Guarda JSFIDDLE

    Mi piace la risposta relativa al passaggio delle funzioni in giro, è una tecnica molto utile.

    Il rovescio della medaglia si può ottenere anche usando pub / sub o usando una variante, un dispatcher, come fa Flux . La teoria è semplicissima, la componente 5 invia un messaggio a cui il componente 3 sta ascoltando. Il componente 3 aggiorna il suo stato che triggers il ri-rendering. Ciò richiede componenti stateful, che, a seconda del punto di vista, possono o meno essere un anti-pattern. Sono contro di loro personalmente e preferirei che qualcos’altro sia in ascolto di dispatch e cambiamenti di stato dall’alto molto in basso (Redux fa questo, ma aggiunge una terminologia aggiuntiva).

     import { Dispatcher } from flux import { Component } from React const dispatcher = new Dispatcher() // Component 3 // Some methods, such as constructor, omitted for brevity class StatefulParent extends Component { state = { text: 'foo' } componentDidMount() { dispatcher.register( dispatch => { if ( dispatch.type === 'change' ) { this.setState({ text: 'bar' }) } } } render() { return 

    { this.state.text }

    } } // Click handler const onClick = event => { dispatcher.dispatch({ type: 'change' }) } // Component 5 in your example const StatelessChild = props => { return }

    Il bundle di dispatcher con Flux è molto semplice, registra semplicemente i callback e li richiama quando si verifica una spedizione, passando attraverso il contenuto della spedizione (nell’esempio qui sopra non c’è un payload con la spedizione, semplicemente un messaggio id). È ansible adattarlo a pub / sub tradizionali (ad es. Utilizzando EventEmitter dagli eventi, o qualche altra versione) molto facilmente se questo ha più senso per te.

    Ho trovato la seguente soluzione operativa per passare l’argomento della funzione Click da child al componente padre con param:

    class genitore:

     class Parent extends React.Component { constructor(props) { super(props) // Bind the this context to the handler function this.handler = this.handler.bind(this); // Set some state this.state = { messageShown: false }; } // This method will be sent to the child component handler(param1) { console.log(param1); this.setState({ messageShown: true }); } // Render the child component and set the action property with the handler as value render() { return  }} 

    class bambino:

     class Child extends React.Component { render() { return ( 
    {/* The button will execute the handler function set by the parent component */}
    ) } }

    Quando hai bisogno di comunicare tra un bambino e un genitore a qualsiasi livello, allora è meglio usare il contesto . Nel componente padre definire il contesto che può essere invocato dal bambino come

    Nel componente principale nel componente del caso 3

      static childContextTypes = { parentMethod: React.PropTypes.func.isRequired }; getChildContext() { return { parentMethod: (parameter_from_child) => this.parentMethod(parameter_from_child) }; } parentMethod(parameter_from_child){ // update the state with parameter_from_child } 

    Ora nel componente figlio (componente 5 nel tuo caso), basta dire a questo componente che vuole usare il contesto del suo genitore.

      static contextTypes = { parentMethod: React.PropTypes.func.isRequired }; render(){ return( this.context.parentMethod(new_state_value)} underlayColor='gray' >  update state in parent component   )} 

    puoi trovare il progetto Demo al repository

     
    this.setState({showChart: true})} />
    {console.log(this.props)}
    Try this example to write inline setState, it avoids creating another function.