2017-01-19 3 views
1

Ich habe eine Komponente, die eine beobachtbare als Eigenschaft hat:Detect-Update in beobachtbaren prop

class Store { 
    @observable color = "red" 
} 

const store = new Store(); 

@observer 
class MyComponent extends React.Component { 
    componentWillReceiveProps(nextProps) { 
    // Not called! 
    console.log("Component will receive props", nextProps.store.color) 
    } 
    componentDidMount() { 
    console.log("Component did mount", this.props.store.color) 
    } 
    changeColor =() => { 
    this.props.store.color = (this.props.store.color==="red")? "blue":"red"; 
    }; 
    render() { 
    return <div> 
     color: {this.props.store.color} 
     <button onClick={this.changeColor}>Change color</button> 
    </div> 
    } 
}; 

ReactDOM.render(<MyComponent store={store} />, document.body) 

Mein Problem ist, dass componentWillReceiveProps nie aufgerufen wird, wenn die beobachtete Variable geändert wird (durch Klicken auf die Schaltfläche), noch ist componentDidReceiveProps oder shouldComponentUpdate. Allerdings kann ich im gerenderten Code sehen, dass die Farbe tatsächlich im Laden geändert wird.

Antwort

3

tl; dr: Verwenden Sie componentWillUpdate und componentDidUpdate


Das Objekt Store geben als eine Stütze ändert sich nie, auch wenn sein Inhalt ändert. Der Trick bei der Verwendung von @observable ist, dass es das Update in der Komponente auslösen wird, ohne die Requisiten zu ändern. Das Verwenden von Lifecycle-Funktionen wie , componentWillReceiveProps und componentDidReceiveProps funktioniert nicht mit, da sie ausgelöst werden, wenn sich die Requisiten oder der Status der Komponente ändern. Der mobx doc erklärt es im Abschnitt shouldComponentUpdate gut.

Also, um ein Update in einer Observable zu fangen, müssen wir ein wenig tiefer in den Lebenszyklus-Stack gehen und componentWillUpdate und componentDidUpdate verwenden.

So sollte der Code wie folgt aussehen:

@observer 
class MyComponent extends React.Component { 
    componentWillReceiveProps(nextProps) { 
    // Not called! 
    console.log("Component will receive props", nextProps.store.color) 
    } 
    componentWillUpdate(nextProps) { 
    console.log("Component will update", nextProps.store.color) 
    } 
    componentDidMount() { 
    console.log("Component did mount", this.props.store.color) 
    } 
    changeColor =() => { 
    this.props.store.color = (this.props.store.color==="red")? "blue":"red"; 
    }; 
    render() { 
    return <div> 
     color: {this.props.store.color} 
     <button onClick={this.changeColor}>Change color</button> 
    </div> 
    } 
}; 

JS Bin: http://jsbin.com/voqugezaya/edit?js,console,output

Unter der Abdeckung, mobx-react verwendet die forceUpdate Funktion die Komponente ausgelöst werden, ohne notwendigerweise eine Änderung der Objekte neu zu rendern in seinen Requisiten (nur ihr Inhalt ändert sich).

Außerdem gibt es eine neue Funktion, die von mobx eingeführt wurde und die beim Debugging sehr hilfreich ist: componentWillReact.

+0

der seltsame Teil hier ist ich eine App abgeschlossen, wo 'componentWillReceiveProps' tatsächlich aufgerufen wird. Danke – Ricbermo

0

Sollten stattdessen die mobx lifecycle-Hook-Funktionen verwendet werden? (z. B. componentWillReact) Siehe die Dokumentation unter https://mobx.js.org/refguide/observer-component.html

+0

'componentWillReact' ist in der Tat gültig. Ich bevorzuge es nicht, weil es nur von Mobx-Events ausgelöst wird (also nicht, wenn Requisiten aktualisiert werden). Außerdem gibt es kein 'componentDidReact', so dass es auch den Lebenszyklus nicht abdeckt. –