2016-05-12 11 views
1

Gibt es eine Möglichkeit, so etwas mit mobx zu tun?Vergleichen von this.props.prop und nextProps.prop mit mobx

componentWillUpdate(nextProps) { 
    if (this.props.prop !== nextProps.prop) { 
    /* side effect, ex. router transition */ 
    } 
} 

Aus meiner Erfahrung ist this.props.prop immer gleich nextProps.prop auch in componentWill- Haken ...

UPD Hier speziellere Anwendungsfall ist - einfaches Login-Szenario:

Shop

class AppStore { 
    @observable viewer = new ViewerStore(); 
} 

class ViewerStore { 
    @observable id; 
    @observable name; 
    @observable error; 

    fromJSON(json = {}) { 
    this.id = json.id; 
    this.name = json.name; 
    } 

    clearError() { 
    this.error = null; 
    } 

    login({ email, password }) { 
    fetch('/login', { 
     method: 'POST', 
     body: JSON.stringify({ 
     email, 
     password 
     }), 
     credentials: 'same-origin' 
    }) 
    .then(json => { 
     this.fromJSON(json); 
    }) 
    .catch(({ error }) => { 
     this.error = error; 
    }) 
    } 
} 

Reagieren Teil

class LogInPage extends Component { 
    componentWillUpdate(nextProps) { 
    if (nextProps.viewer.id && !this.props.viewer.id) { 
     this.props.viewer.clearError(); 
     this.props.onSuccess(); 
    } 
    } 

    login = e => { 
    e.preventDefault(); 
    this.props.viewer.login({ 
     email: e.target.elements['email'].value, 
     password: e.target.elements['password'].value, 
    }); 
    } 

    render() { 
    return (
     <div> 
     <h1>Log In</h1> 
     <form onSuccess={this.login}> 
      <input type="text" name="email" /> 
      <input type="password" name="password" /> 
      <input type="submit" /> 
     </form> 
     { this.props.viewer.error && (
      <div> 
      <b>Error</b>: {this.props.viewer.error} 
      </div> 
     )} 
     </div> 
    ); 
    } 
} 

const store = new AppStore(); 
ReactDOM.render(<LogInPage 
    viewer={store.viewer} 
    onSuccess={() => alert("Hello!")} 
/> 
, container); 

Also im Grunde möchte ich nur in der Lage sein, etwas zu tun, wenn Betrachter id wechselt von undefined etwas

Antwort

0

In 99,9% der Fälle, weil irgendwo passiert, sonst sind in deinem Code Requisiten direkt mutiert. Und das ist nicht erlaubt zu reagieren.

Typische Szenarien umfassen:

var myObject = this.props.someObject; // myObject is a POINTER to props, not copy 
myObject.attribute = newAttribute;  // Now props are directly mutated 

var myArray = this.props.someArray; 
myArray.splice(a,b);     // splice directly mutates array 

zu lösen, eine richtige Kopie der Requisiten-Objekt, bevor Sie die Stütze aktualisieren.

0

Nun, eigentlich das Problem geschah, weil ich einen mobx Speicher als Einzelstütze (um es Methoden wie this.props.store.update() zu nennen) übergeben, so dass, obwohl, wenn etwas im Laden ändert, Komponente von mobx aktualisiert wird, nextProps hält nach wie vor die gleicher Bezug zu diesem Geschäft.

Ich endete schließlich mit der Destrukturierung Speicher in Komponenten Requisiten, wenn ich diese Art von Prüfung brauche.

+0

Können Sie beschreiben, warum die Route geändert werden muss, und warum das die Verantwortung von der Komponente, die das gesamte Geschäft erhält, sein muss? Ich würde erwarten, dass dies in einem Geschäft passiert, das zum Beispiel einen bestimmten Artikel erhält. Vielleicht einen Code teilen? – mweststrate

2

Danke für das Update, das verdeutlicht die Frage sehr. Es hängt ein bisschen davon ab, was Sie tun wollen, aber wenn Sie das Rendering Ihrer Komponente ändern wollen, reicht es, Ihre Komponente mit @observer aus dem mobx-react Paket zu dekorieren. Es wird dann automatisch neu gerendert, wenn sich der Laden ändert.

Wenn Sie weitere Aktionen ausführen möchten, können Sie eine Autorun in Ihrem componentWillMount einrichten. Wie

componentWillMount() { 
    this.autorunDisposer = mobx.autorun(() => { 
     if (nextProps.viewer.id && !this.props.viewer.id) { 
      this.props.viewer.clearError(); 
      this.props.onSuccess(); 
     } 
    }) 
} 

Aber ich sehe nicht, dieses Muster sehr oft, wie oft ist es sauberer, diese Art von Logik zu haben, gerade in Ihrem Geschäft. Persönlich würde ich eine Login-Formularkomponente erwarten, die ungefähr so ​​aussieht:

@observer class RequiresLogin extends Component { 
    render() { 
     if (this.props.viewerStore.id !== undefined) { 
      return this.props.children 
     } else { 
      return <LoginPage viewer={this.props.viewerStore}/> 
     } 
    } 
} 

@observer class MyTestPage extends Component { 
    render() { 
     return <RequiresLogin viewer={this.props.viewerStore}> 
      Secret Area! 
     </RequiresLogin> 
    } 
} 

@observer class LogInPage extends Component { 
    login = e => { 
    e.preventDefault(); 
    this.props.viewer.login({ 
     // tip: use React refs or the onChange handler to update local state: 
     email: e.target.elements['email'].value, 
     password: e.target.elements['password'].value, 
    }); 
    } 

    render() { 
    if (this.props.viewer.id) 
     return null; // no need to show login form 
    return (
     <div> 
     <h1>Log In</h1> 
     <form onSuccess={this.login}> 
      <input type="text" name="email" /> 
      <input type="password" name="password" /> 
      <input type="submit" /> 
     </form> 
     { this.props.viewer.error && (
      <div> 
      <b>Error</b>: {this.props.viewer.error} 
      </div> 
     )} 
     </div> 
    ); 
    } 
} 
+0

Vielen Dank für die Antwort! Aber wie greife ich auf 'nextProps' in' componentWillMount() '? – khrykin

Verwandte Themen