wake-up-neo.net

Wie kann ich den Status der Eltern in React aktualisieren?

Meine Struktur sieht folgendermaßen aus:

Component 1  

 - |- Component 2


 - - |- Component 4


 - - -  |- Component 5  

Component 3

Komponente 3 sollte abhängig vom Status von Komponente 5 einige Daten anzeigen. Da Requisiten unveränderlich sind, kann ich ihren Status nicht in Komponente 1 speichern und weiterleiten, oder? Und ja, ich habe über redux gelesen, möchte es aber nicht verwenden. Ich hoffe, dass es möglich ist, es nur mit reagieren zu lösen. Liege ich falsch?

199
wklm

Für die Kommunikation zwischen Eltern und Eltern sollten Sie eine Funktion übergeben, die den Status von Eltern zu Kind wie folgt festlegt

class Parent extends React.Component {
  constructor(props) {
    super(props)

    this.handler = this.handler.bind(this)
  }

  handler() {
    this.setState({
      someVar: someValue
    })
  }

  render() {
    return <Child handler = {this.handler} />
  }
}

class Child extends React.Component {
  render() {
    return <Button onClick = {this.props.handler}/ >
  }
}

Auf diese Weise kann das Kind den Zustand der Eltern mit dem Aufruf einer Funktion aktualisieren, die mit Requisiten übergeben wird.

Sie müssen jedoch die Struktur Ihrer Komponenten überdenken, da Komponenten 5 und 3 meines Erachtens nicht miteinander zusammenhängen.

Eine mögliche Lösung besteht darin, sie in eine Komponente höherer Ebene einzuwickeln, die den Status von Komponente 1 und 3 enthält. Diese Komponente setzt den Status der unteren Ebene über Requisiten.

406
Ivan

Ich habe die folgende Arbeitslösung gefunden, um das onClick-Funktionsargument vom untergeordneten Element an die übergeordnete Komponente zu übergeben:

Version mit einer Methode übergeben ()

//ChildB component
class ChildB extends React.Component {

    render() {

        var handleToUpdate  =   this.props.handleToUpdate;
        return (<div><button onClick={() => handleToUpdate('someVar')}>
            Push me
          </button>
        </div>)
    }
}

//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 (<div>
                    <ChildB handleToUpdate = {handleToUpdate.bind(this)} /></div>)
    }
}

if(document.querySelector("#demo")){
    ReactDOM.render(
        <ParentA />,
        document.querySelector("#demo")
    );
}

Schau dir JSFIDDLE an

Version mit Übergabe einer Pfeilfunktion

//ChildB component
class ChildB extends React.Component {

    render() {

        var handleToUpdate  =   this.props.handleToUpdate;
        return (<div>
          <button onClick={() => handleToUpdate('someVar')}>
            Push me
          </button>
        </div>)
    }
}

//ParentA component
class ParentA extends React.Component { 
    constructor(props) {
        super(props);
    }

    handleToUpdate = (someArg) => {
            alert('We pass argument from Child to Parent: ' + someArg);
    }

    render() {
        return (<div>
            <ChildB handleToUpdate = {this.handleToUpdate} /></div>)
    }
}

if(document.querySelector("#demo")){
    ReactDOM.render(
        <ParentA />,
        document.querySelector("#demo")
    );
}

Schau dir JSFIDDLE an

32
Roman

Ich mag die Antwort in Bezug auf die Weitergabe von Funktionen, es ist eine sehr praktische Technik.

Auf der anderen Seite können Sie dies auch mit pub/sub oder mit einer Variante, einem Dispatcher, wie Flux tun. Die Theorie ist sehr einfach: Lassen Sie die Komponente 5 eine Nachricht versenden, auf die die Komponente 3 wartet. Die Komponente 3 aktualisiert dann ihren Status, wodurch das erneute Rendern ausgelöst wird. Dies erfordert Stateful-Komponenten, die je nach Standpunkt ein Anti-Pattern sein können oder nicht. Ich bin persönlich gegen sie und möchte lieber, dass etwas anderes von oben nach unten auf Abfertigungen und Statusänderungen wartet (Redux tut dies, fügt jedoch zusätzliche Terminologie hinzu).

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 <h1>{ this.state.text }</h1>
  }
}

// Click handler
const onClick = event => {
  dispatcher.dispatch({
    type: 'change'
  })
}

// Component 5 in your example
const StatelessChild = props => {
  return <button onClick={ onClick }>Click me</button> 
}

Das Dispatcher-Paket mit Flux ist sehr einfach. Es registriert einfach Callbacks und ruft sie auf, wenn ein Dispatch auftritt, und durchläuft den Inhalt des Dispatches (im obigen knappen Beispiel gibt es keine payload mit dem Dispatch, nur eine Nachrichten-ID). Sie können dies sehr einfach an traditionelle pub/sub-Modi (z. B. durch Verwendung des EventEmitter von Ereignissen oder einer anderen Version) anpassen, wenn dies für Sie sinnvoller ist.

6
Matt Styles

Ich habe die folgende Arbeitslösung gefunden, um das onClick-Funktionsargument mit param an die übergeordnete Komponente zu übergeben:

elternklasse:

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 <Child action={this.handler} />
}}

kinderklasse:

class Child extends React.Component {
render() {
    return (
        <div>
            {/* The button will execute the handler function set by the parent component */}
            <Button onClick={this.props.action.bind(this,param1)} />
        </div>
    )
} }
4
H. parnian

Wann immer Sie von Kind zu Eltern auf einer niedrigeren Ebene kommunizieren müssen, sollten Sie context verwenden. Definieren Sie in der übergeordneten Komponente den Kontext, den das untergeordnete Element aufrufen kann, z 

In der übergeordneten Komponente in Ihrer Fallkomponente 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
}

Sagen Sie jetzt in der untergeordneten Komponente (Komponente 5 in Ihrem Fall) diese Komponente, die der Kontext des übergeordneten Elements verwenden soll.

 static contextTypes = {
       parentMethod: React.PropTypes.func.isRequired
     };
render(){
    return(
      <TouchableHighlight
        onPress={() =>this.context.parentMethod(new_state_value)}
         underlayColor='gray' >


            <Text> update state in parent component </Text>


      </TouchableHighlight>
)}

demo-Projekt finden Sie unter Repo

2

wenn Sie also die übergeordnete Komponente aktualisieren möchten,

 class ParentComponent extends React.Component {
        constructor(props){
            super(props);
            this.state = {
               page:0
            }
        }

        handler(val){
            console.log(val) // 1
        }

        render(){
          return (
              <ChildComponent onChange={this.handler} />
           )
       }
   }


class ChildComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
             page:1
        };
    }

    someMethod = (page) => {
        this.setState({ page: page });
        this.props.onChange(page)
    }

    render() {
        return (
       <Button
            onClick={() => this.someMethod()} 
       > Click
        </Button>
      )
   }
}

Hier ist onChange ein Attribut, dessen "Handler" -Methode an seine Instanz gebunden ist. Wir haben den Methodenhandler an die Child-Klassenkomponente übergeben, um ihn über die onChange-Eigenschaft in ihrem props-Argument zu erhalten.

Das Attribut onChange wird in einem Requisitenobjekt wie folgt gesetzt:

props ={
onChange : this.handler
}

und an die untergeordnete Komponente übergeben

So kann die Child-Komponente auf den Wert von name im Requisitenobjekt wie folgt zugreifen: props.onChange

Dies geschieht durch die Verwendung von Render Requisiten.

Jetzt hat die Child-Komponente eine Schaltfläche „Click“ mit einem festgelegten onclick-Ereignis, um die Handlermethode aufzurufen, die ihr über onChnge in ihrem props-Argumentobjekt übergeben wurde. Jetzt enthält this.props.onChange in Child die Ausgabemethode in der Parent-Klasse Reference und credits: Bits and Pieces

1
Preetham NT

Es scheint, dass wir nur Daten von einem Elternteil an ein Kind übergeben können, da eine Reaktion den unidirektionalen Datenfluss fördert. Um jedoch zu bewirken, dass sich ein Elternteil selbst aktualisiert, wenn in seiner "Kindkomponente" etwas passiert, verwenden wir im Allgemeinen eine sogenannte "Rückruffunktion".

Wir übergeben die im Elternteil definierte Funktion als "Requisiten" an das Kind und rufen diese Funktion von dem Kind auf, das sie in der Elternkomponente auslöst.

-------------------------------------------------- -----------------------------

class Parent extends React.Component {
  handler = (Value_Passed_From_SubChild) => {
    console.log("Parent got triggered when a grandchild button was clicked");
    console.log("Parent->Child->SubChild");
    console.log(Value_Passed_From_SubChild);
  }
  render() {
    return <Child handler = {this.handler} />
  }
}
class Child extends React.Component {
  render() {
    return <SubChild handler = {this.props.handler}/ >
  }
}
class SubChild extends React.Component { 
  constructor(props){
   super(props);
   this.state = {
      somethingImp : [1,2,3,4]
   }
  }
  render() {
     return <button onClick = {this.props.handler(this.state.somethingImp)}>Clickme<button/>
  }
}
React.render(<Parent />,document.getElementById('app'));

 HTML
 ----
 <div id="app"></div>

In diesem Beispiel können wir Daten von SubChild -> Child -> Parent übergeben, indem wir die Funktion an das direkte Child übergeben.

1
Vishal Bisht

Ich habe viele Male eine der bestbewerteten Antworten auf dieser Seite verwendet, aber während ich React lernte, habe ich einen besseren Weg gefunden, dies ohne Bindung und ohne Inline-Funktion in Requisiten zu tun.

Schau einfach hier:

class Parent extends React.Component {

  constructor() {
    super();
    this.state={
      someVar: value
    }
  }

  handleChange=(someValue)=>{
    this.setState({someVar: someValue})
  }

  render() {
    return <Child handler={this.handleChange} />
  }

}

export const Child = ({handler}) => {
  return <Button onClick={handler} />
}

Die Taste befindet sich in einer Pfeilfunktion:

handleChange=(someValue)=>{
  this.setState({someVar: someValue})
}

Sie können mehr lesen hier . Hoffe das wird nützlich für jemanden =)

-Wir können ParentComponent und mit der handleInputChange-Methode erstellen, um den ParentComponent-Status zu aktualisieren. Importieren Sie die ChildComponent, und wir übergeben zwei Requisiten von der übergeordneten Komponente an die untergeordnete Komponente ie.handleInputChange. 

import React, { Component } from 'react';
import ChildComponent from './ChildComponent';

class ParentComponent extends Component {
  constructor(props) {
    super(props);
    this.handleInputChange = this.handleInputChange.bind(this);
    this.state = {
      count: '',
    };
  }

  handleInputChange(e) {
    const { value, name } = e.target;
    this.setState({ [name]: value });
  }

  render() {
    const { count } = this.state;
    return (
      <ChildComponent count={count} handleInputChange={this.handleInputChange} />
    );
  }
}
  • Jetzt erstellen wir die ChildComponent-Datei und speichern sie als ChildComponent.jsx. Diese Komponente ist zustandslos, da die untergeordnete Komponente keinen Status hat. Wir verwenden die Bibliothek für Requisiten für die Prüfung von Requisiten.

    import React from 'react';
    import { func, number } from 'prop-types';
    
    const ChildComponent = ({ handleInputChange, count }) => (
      <input onChange={handleInputChange} value={count} name="count" />
    );
    
    ChildComponent.propTypes = {
      count: number,
      handleInputChange: func.isRequired,
    };
    
    ChildComponent.defaultProps = {
      count: 0,
    };
    
    export default ChildComponent;
    
1
Sachin Metkari

Ich möchte der am meisten bewerteten Antwort danken, dass sie mir die Idee meines eigenen Problems gegeben hat, im Wesentlichen die Variation davon mit der Pfeilfunktion und dem Übergeben von param von der Kindkomponente:

 class Parent extends React.Component {
  constructor(props) {
    super(props)
    // without bind, replaced by arrow func below
  }

  handler = (val) => {
    this.setState({
      someVar: val
    })
  }

  render() {
    return <Child handler = {this.handler} />
  }
}

class Child extends React.Component {
  render() {
    return <Button onClick = {() => this.props.handler('the passing value')}/ >
  }
}

Hoffe es hilft jemandem.

0
Ardhi