2017-05-31 5 views
2

Ich habe hier eine Mauer getroffen, was bedeutet, ich kann nicht völlig herausfinden, warum die nächsten zwei Versionen von Code so unterschiedlich verhalten.Reagieren dynamisch Rendering-Komponente (Objekt zuweisen vs. Funktion zurück)

In der ersten Version, wenn ich ein this.childComponent = (<ChildComp />) Initialisierungsphase seine Requisiten scheinen nicht zu aktualisieren, wenn ich die Parent ‚s Zustand ändern (via setState()). Dies geschieht, obwohl der setState() tatsächlich aufgerufen wird und der Parent-Status aktualisiert wird.

In der zweiten Version, wenn ich tatsächlich eine Funktion initialisiere, die die Komponente (this.childComponent =() => {return (<ChildComp />)}) zurückgibt, funktioniert alles wie ein Charme, Requisiten werden aktualisiert. Ich benutze die zweite Version (da es funktioniert), aber ich würde gerne verstehen, warum das funktioniert und das erste nicht.

Hier ist das Kind Komponente:

class Child extends React.Component { 
    render() { 
    return (
     <button onClick=(this.props.setValue())> 
     {this.props.value} 
     </button> 
    ) 
    } 
} 

ich die nächsten zwei Versionen der Elternkomponente haben:

1.

class Parent extends React.Component { 
    constructor() { 
    this.state = { 
     value: 1 
    } 
    this.childComponent = (
     <Child value={this.state.value} 
     setValue={() => this.setValue()}/> 
    ) 
    } 
    setValue() { 
    this.setState({value: 2}) 
    } 
    render() { 
    return ({this.childComponent}) 
    } 
} 

2. (die this.childComponent ist jetzt eine Funktion, die das reaktive Element zurückgibt)

class Parent extends React.Component { 
    constructor() { 
    this.state = { 
     value: 1 
    } 
    this.childComponent =() => { 
     return (
     <Child value={this.state.value} 
     setValue={() => this.setValue()}/> 
    ) 
    } 
    } 
    setValue() { 
    this.setState({value: 2}) 
    } 
    render() { 
    return ({this.childComponent()}) 
    } 
} 

Ich habe versucht, den Code zu vereinfachen, damit mein Problem leichter zu verstehen ist.

Vielen Dank im Voraus

+1

In Ihrer ersten (gebrochenen) Version wird die untergeordnete Komponente statisch definiert und nie wieder geändert. – pscl

+1

Sie haben keine Rückkehr im ersten Fall 'render() { Rückgabe {this.childComponent} }' kann funktionieren, sonst ist die untergeordnete Komponente statisch –

+0

Got it, danke für die Erklärungen –

Antwort

1

Reagieren verwendet eine Strategie reconciliation aufgerufen, um effizient den DOM zu aktualisieren jedes Mal, wenn es eine Änderung in seinem internen Zustand. In der Regel geschieht dies nach einem Anruf setState.

In Ihrem ersten Beispiel die render Methode innerhalb der Parent Komponente liefert immer die gleiche Child Komponente, wie es in den constructor nur einmal erstellt wird. Aus diesem Grund findet der Abgleichsalgorithmus keine Änderungen, da keine vorhanden sind.

Ich möchte darauf hinweisen, dass <Child value={this.state.value} setValue={() => this.setValue()}/> ist nur syntaktischer Zucker für React.createElement(Child, {value: this.state.value, setValue:() => this.setValue()}, null). createElement gibt einfach ein Objekt zurück.

In Ihrem zweiten Beispiel rufen Sie mit jedem render Anruf childComponent an, der wiederum eine neue Komponente Child erstellt.

1

Sie seit

this.childComponent = (
    <Child value={this.state.value} 
    setValue={() => this.setValue()}/> 
) 

wurde im Konstruktor definiert keine Rückkehr im ersten Fall haben, die nur einmal ausgeführt wird und einen statischen Wert jetzt.

während es funktioniert, da es eine Funktion ist, die jedes Mal ausgeführt wird, wenn es aufgerufen wird.

Wenn Sie nach der ersten Methode gehen wollen, definieren Sie die Child-Komponente im Render und nicht im Konstruktor, da Render bei jeder Änderung aufgerufen wird. Dein Code hatte auch viele Fehler. Siehe den Arbeits Schnipsel unten

class Parent extends React.Component { 
 
    constructor() { 
 
    super(); 
 
    this.state = { 
 
     value: 1 
 
    } 
 
    
 
    } 
 
    setValue() { 
 
    this.setState({value: 2}) 
 
    } 
 
    render() { 
 
     const childComponent = (
 
     <Child value={this.state.value} 
 
     setValue={() => this.setValue()}/> 
 
    ) 
 
    return (<div>{childComponent}</div>) 
 
    } 
 
} 
 

 
class Child extends React.Component { 
 
    render() { 
 
    return (
 
     <button onClick={this.props.setValue}> 
 
     {this.props.value} 
 
     </button> 
 
    ) 
 
    } 
 
} 
 

 
ReactDOM.render(<Parent/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<div id="app"></div>

+0

Hinzugefügt eine Erklärung und eine Arbeit Schnipsel mit der ersten Methode –

Verwandte Themen