有办法用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);基本上,当查看器id从undefined切换到某物时,我只想做一些事情
发布于 2016-05-12 17:59:44
谢谢你的更新,这就澄清了很多问题。这在一定程度上取决于您想要做什么,但是如果您想要更改组件的呈现,就足以从@observer包中用mobx-react来装饰您的组件。然后,当商店更改时,它将自动重新呈现。
如果要执行任何其他操作,可以在componentWillMount中设置自动运行。喜欢
componentWillMount() {
this.autorunDisposer = mobx.autorun(() => {
if (nextProps.viewer.id && !this.props.viewer.id) {
this.props.viewer.clearError();
this.props.onSuccess();
}
})
}但我并不经常看到这种模式,因为在你的商店里有这样的逻辑往往更干净。就我个人而言,我希望登录表单组件看起来像这样:
@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>
);
}
}发布于 2016-05-12 14:10:56
在99%的情况下,发生这种情况是因为代码道具中的其他地方是直接变异的。这是不允许的反应。
典型场景包括:
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若要解决此问题,请在更新道具之前创建道具对象的适当副本。
发布于 2016-05-12 16:23:29
实际上,问题的发生是因为我将一个mobx存储作为单一的支柱(为了调用它的方法,比如this.props.store.update()),所以即使在存储中发生了一些变化,组件被mobx更新了,nextProps仍然保持着对该存储的相同引用。
最后,当我需要这样的检查时,我终于把商店破坏成了组件的道具。
https://stackoverflow.com/questions/37185889
复制相似问题