编辑:检出git存储库以获取最小示例:https://github.com/maximilianschmitt/blind-lifecycle
我有一个组件RequireUser
,试图确保用户已登录,否则将不呈现其子级。它的父组件App
应该知道是否需要用户,并在需要时呈现登录表单。
问题是,App
组件会在RequireUser
组件之后像这样在树中安装:
App
RequireUser
SomeOtherComponent
在
RequireUser
的componentDidMount
中,我正在触发将requireLogin
的UserStore
变量设置为loginRequired
的操作true
。这不会更新父组件(
App
),因为尚未安装它,因此不能将更改注册到存储中。class RequireUser extends React.Component {
constructor() {
super();
this.state = alt.stores.UserStore.getState();
}
componentDidMount() {
this.unlisten = alt.stores.UserStore.listen(this.setState.bind(this));
if (!this.state.requireUser) {
UserActions.requireUser();
// using setTimeout will work:
// setTimeout(() => UserActions.requireUser());
}
}
componentWillUnmount() {
this.unlisten();
}
render() {
if (this.state.requireUser) {
return <div>I have required your user</div>;
}
return <div>I will require your user</div>;
}
}
class App extends React.Component {
constructor() {
super();
this.state = alt.stores.UserStore.getState();
}
componentDidMount() {
this.unlisten = alt.stores.UserStore.listen(this.setState.bind(this));
}
componentWillUnmount() {
this.unlisten();
}
render() {
return (
<div>
<div>User required? {this.state.requireUser + ''}</div>
<RequireUser />
</div>
);
}
}
输出:
需要用户吗?假
我已要求您的用户
如果我在
setTimeout
中使用RequireUser
,则App
会接收状态更改和呈现,但仅在闪烁之后:需要用户吗?真正
我已要求您的用户
我感觉到我在做的是反模式,对于提出比使用setTimeout闪烁更优雅的解决方案的建议,我将不胜感激。谢谢!
最佳答案
我建议的答案是将其添加到App组件中:
componentDidMount() {
// setup listener for subsequent changes
alt.stores.UserStore.listen(this.onChange);
// grab the current state now that we're mounted
var userStoreState = alt.stores.UserStore.getState();
this.setState(userStoreState);
}
无法避免双重渲染。您的RequireUser组件已经执行了两个渲染。
RequireUser的初始呈现
componentDidMount()回调
派遣行动
UserStore接收调度的动作并更新其状态
发出变更通知
RequireUser根据状态更改设置状态
二次渲染RequireUser
但是您的代码库仍然被认为是Flux,并且确实遵循针对React应用程序的模式。本质上,您有一个加载状态...一种实际上不知道是否需要用户的状态。根据UserActions.requireUser()的功能,可能需要也可能不需要。
您可能会考虑重构
如果将RequireUser重写为仅查看组件,则可以修复双重渲染。这意味着既没有侦听器,也没有内部设置状态。这个组件只是根据传入的props渲染元素。实际上,您的RequireUser组件都是:
class RequireUser extends React.Component {
render() {
if (this.props.requireUser) {
return <div>I have required your user</div>;
}
return <div>I will require your user</div>;
}
}
然后,您将使您的App组件成为控制器视图。在此处添加了侦听器,并且状态的任何更改都通过props向下传播。现在我们可以在componentWillMount回调中进行设置。这给了我们单一的渲染行为。
class App extends React.Component {
(other lifecycle methods)
componentWillMount() {
if (!this.state.requireUser) {
UserActions.requireUser();
}
var userStoreState = alt.stores.UserStore.getState();
this.setState(userStoreState);
}
componentDidMount() {
(same as above)
}
render() {
return (
<div>
<div>User required? {this.state.requireUser + ''}</div>
<RequireUser requireUser={this.state.requireUser} />
</div>
);
}
}
Flux体系结构和控制器视图/视图:https://facebook.github.io/flux/docs/overview.html#views-and-controller-views
关于javascript - React + Alt:生命周期差距,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33550763/