2016-05-12 22 views
1

有沒有辦法像mobx一樣做這樣的事情?將this.props.prop和nextProps.prop與mobx比較

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

從我的經驗,this.props.prop總是等於nextProps.prop即使在componentWill-鉤...

UPD這裏有更具體的用例 - 簡單的登錄場景:

商店

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; 
    }) 
    } 
} 

陣營部分

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); 

所以基本上,我只是希望能夠做一些事情,當觀衆從undefinedid開關的東西

回答

0

在案件99.9%,這是因爲某處否則你的代碼中的道具會直接發生變異。這是不允許的反應。

典型場景的包括:

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 

來解決,讓你更新的道具之前道具的正確的複製對象。

0

嗯,其實這個問題發生,因爲我通過mobx店作爲單一支柱(爲了調用它就像this.props.store.update()方法),所以即使當事情在商店的變化,組件由mobx更新,nextProps仍佔據與該商店相同的參考。

當我需要這種檢查時,我最終終於將解構存儲到組件的道具中。

+0

你能描述一下爲什麼路線必須改變,爲什麼這必須是由接收全倉組件中的責任?例如,我希望這種情況發生在收到特定物品的商店中。也許分享一些代碼? – mweststrate

2

感謝您的更新,澄清了很多問題。這取決於你想做什麼,但是如果你想改變你的組件的渲染,就可以用mobx-react包中的@observer來裝飾你的組件。它會在商店更改時自動重新呈現。

如果你想做任何額外的動作,你可以在你的componentWillMount中設置自動運行。像

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

但我沒有經常看到這種模式,因爲經常有這種邏輯只是在你的商店更清潔。我個人期待一個登錄表單組件rougly這個樣子:

@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

謝謝你的回答!但是,如何訪問'componentWillMount()'中的'nextProps'? – khrykin