2016-05-12 24 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