2017-05-25 17 views
0

Ich stieß auf ein Problem mit der Aktualisierung eines Teils des Zustands, der eine Liste ist, die an untergeordnete Elemente einer Komponente weitergegeben wird.Reagieren mit Listen im Zustand, wie man neuen Zustand einstellt?

Ich übergebe eine Liste an ein Kind, aber dann habe Schwierigkeiten, diese Liste zu aktualisieren und das Kind den neuen Zustand widerspiegeln;

<ItemsClass items={this.state.items1} /> 

Wenn ich den Wert von this.state.items1 ändern, wird die Komponente nicht mit dem neuen Wert machen.

this.setState({items1: []}); // this has no effect 

Wenn ich jedoch die bereits bestehenden Array ändern (nicht ersetzen sie einen neuen leeren neu), macht die Komponente, wie ich will;

this.setState(state => { clearArray(state.items1); return state; }); 

Das heißt, den Funktionszustand Aktualisierung ist nicht rein, das Reagieren heißt es sein sollte.

Das HTML;

<div id='app'></div> 

Die js;

class ItemsClass extends React.Component { 
    constructor(props){ 
    super(props); 

    this.state = {items: props.items}; 
    } 

    render() { 
    var items = this.state.items.map(it => <div key={it.id}>{it.text}</div>); 
    return(
     <div>{items}</div> 
    ); 
    } 
} 

function ItemsFunction(props) { 
    var items = props.items.map(it => <div key={it.id}>{it.text}</div>); 
    return(
     <div>{items}</div> 
    ); 
} 

class App extends React.Component { 
    constructor(props){ 
    super(props); 
    var items = [{id:1, text: 'item 1'}, {id: 2, text: 'item 2'}]; 

    this.state = { 
     items1: items.slice(), 
     items2: items.slice(), 
     items3: items.slice() 
    }; 
    this.clearLists = this.clearLists.bind(this); 
    } 

    clearLists() { 
    // for items1 and items2, clear the lists by assigning new empty arrays (pure). 
    this.setState({items1: [], items2: []}); 

    // for items3, change the already existing array (non-pure). 
    this.setState(state => { 
     while (state.items3.length) { 
     state.items3.pop(); 
     } 
    }) 
    } 

    render() { 
    return (
     <div> 
     <button onClick={this.clearLists}>Clear all lists</button> 
     <h2>Items rendered by class, set list to new empty array</h2> 
     <ItemsClass items={this.state.items1} /> 
     <h2>Items rendered by class, empty the already existing array</h2> 
     <ItemsClass items={this.state.items3} /> 
     <h2>Items rendered by function</h2> 
     <ItemsFunction items={this.state.items2} /> 
     </div> 
    ); 
    } 
} 

ReactDOM.render(<App />, document.getElementById('app')); 

Probieren Sie es aus codepen.

Es scheint, dass die ItemsClass nicht aktualisiert wird, obwohl es mit <ItemsClass items={this.state.items1}/> und this.state.items1 in den übergeordneten Änderungen erstellt wird.

Ist dies das erwartete Verhalten? Wie kann ich den Status in dem ItemsClass Kind vom Eltern aktualisieren? Ich vermisse ich etwas? Dieses Verhalten scheint ziemlich fehleranfällig zu sein, da es leicht ist anzunehmen, dass das Kind dem neuen Zustand folgen sollte, so wie es beim Erstellen des Kindes weitergegeben wurde.

Antwort

2

Sie kopieren die Requisiten von ItemsClass in den Zustand, wenn die Komponente initialisiert wird - Sie setzen den Zustand nicht zurück, wenn sich die Requisiten ändern, sodass die Aktualisierungen Ihrer Komponente nicht angezeigt werden. Um das docs zu zitieren:

Hüten Sie sich vor diesem Muster, da Zustand mit irgendwelchen Requisiten-Update nicht auf dem neuesten Stand sein wird. Anstatt Requisiten zu synchronisieren, möchten Sie oft den Status erhöhen.

Wenn Ihre Komponente etwas zu tun hat, wenn die Requisiten zu ändern, können Sie die componentWillReceieveProps Lifecycle Haken so zu tun, verwenden (beachten Sie, dass es nicht laufen bekommt, wenn die Komponente zunächst montiert, nur auf nachfolgendem prop-Updates).

Das heißt, es gibt null Grund für Sie, die Requisiten, hier zu duplizieren (und ehrlich gesagt gibt es selten einen guten Grund, so im Allgemeinen zu tun) - nur die Requisiten direkt verwenden, wie Sie mit ItemsFunction tun, und alles wird Aufenthalt in sync:

class ItemsClass extends React.Component { 
    render() { 
    var items = this.props.items.map(it => <div key={it.id}>{it.text}</div>); 
    return(
     <div>{items}</div> 
    ); 
    } 
} 

Hier ist eine Arbeitsversion Ihres Codepen: http://codepen.io/anon/pen/JNzBPV

Verwandte Themen