调用 Flux Store 操作时 setState 未更新状态
setState is not updating the state by the time the Flux Store action is called
我有两个组件。一个项目容器和一个项目设置面板(以后会有更多的项目设置面板)。
我在面板内有一个开关调用 "switchSubmit" 函数来更新状态,然后调用 "handleSubmit" 函数,该函数包含一个根据开关按钮的值更新 Flux Store 的操作,我正在设置状态,但它似乎始终是调用我的操作时选择的先前值。
我读到 setState 不是同步的,我也看过一些示例,但不知道如何应用正确的调用和函数来设置状态,并在调用操作时准备好更新后的状态我正在编写的这段代码。
这是我的代码:
var React = require('react/addons');
var Actions = require('../../Actions');
var ConfigurationStore = require('../../stores/Configuration');
var Controller = React.createClass({
getInitialState: function () {
ConfigurationStore.reset();
Actions.getConfigurationSettings();
return this.getStateFromStores();
},
getStateFromStores: function () {
return {
configuration: ConfigurationStore.getState()
};
},
componentDidMount: function () {
ConfigurationStore.addChangeListener(this.onStoreChange);
},
componentWillUnmount: function () {
ConfigurationStore.removeChangeListener(this.onStoreChange);
},
onStoreChange: function () {
this.setState(this.getStateFromStores());
},
render: function () {
return (
<section className="section-settings container">
<h1 className="page-header">Projects</h1>
<div className="row">
<div className="col-sm-12">
<div className="row">
<div className="col-sm-3">
</div>
<div className="col-sm-9">
<h2>Project Settings</h2>
<hr />
<ProjectContainer data={this.state.configuration} />
</div>
</div>
</div>
</div>
</section>
);
}
});
var ProjectContainer = React.createClass({
getInitialState: function () {
return {
active: false
};
},
componentWillReceiveProps: function (nextProps) {
this.setState({
active: nextProps.data.active
});
},
render: function () {
return (
<div>
<ProjectPanel data={this.props.data}></ProjectPanel>
</div>
);
}
});
var ProjectPanel = React.createClass({
getInitialState: function () {
return {
active: false
};
},
componentWillReceiveProps: function (nextProps) {
this.setState({
active: nextProps.data.active
});
},
handleSubmit: function () {
Actions.updateConfigurationSettings({
active: this.state.active
});
},
switchSubmit: function(event) {
event.stopPropagation();
this.setState({
active: event.currentTarget.checked
});
this.handleSubmit();
},
render: function() {
var formElements = (
<fieldset>
<SwitchButton
name="switch-1"
onChange={this.switchSubmit}
checked={this.props.active}
/>
</fieldset>
);
}
return (
<div className="project-holder">
<div className="project-config">
<form onSubmit={this.handleSubmit}>
{formElements}
</form>
</div>
</div>
);
}
});
如有任何帮助,我们将不胜感激!
为了直接回答您的问题,setState
接受一个回调,该回调可用于将代码推迟到渲染完成之后。但是,您不需要在您的方案中使用它。
我在您的代码中看到的问题是您有多个 'active' 状态的真实来源。
我已更新您的代码以解决该问题:
var React = require('react/addons');
var Actions = require('../../Actions');
var ConfigurationStore = require('../../stores/Configuration');
var Controller = React.createClass({
getInitialState: function () {
ConfigurationStore.reset();
Actions.getConfigurationSettings();
return this.getStateFromStores();
},
getStateFromStores: function () {
return {
configuration: ConfigurationStore.getState()
};
},
componentDidMount: function () {
ConfigurationStore.addChangeListener(this.onStoreChange);
},
componentWillUnmount: function () {
ConfigurationStore.removeChangeListener(this.onStoreChange);
},
onStoreChange: function () {
this.setState(this.getStateFromStores());
},
render: function () {
return (
<section className="section-settings container">
<h1 className="page-header">Projects</h1>
<div className="row">
<div className="col-sm-12">
<div className="row">
<div className="col-sm-3">
</div>
<div className="col-sm-9">
<h2>Project Settings</h2>
<hr />
<ProjectContainer data={this.state.configuration} />
</div>
</div>
</div>
</div>
</section>
);
}
});
var ProjectContainer = React.createClass({
render: function () {
return (
<div>
<ProjectPanel data={this.props.data}></ProjectPanel>
</div>
);
}
});
var ProjectPanel = React.createClass({
handleSubmit: function () {
// Do something interesting on submit.
},
switchSubmit: function(event) {
event.stopPropagation();
Actions.updateConfigurationSettings({
active: event.target.checked
});
},
render: function() {
var formElements = (
<fieldset>
<SwitchButton
name="switch-1"
onChange={this.switchSubmit}
checked={this.props.data.active}
/>
</fieldset>
);
}
return (
<div className="project-holder">
<div className="project-config">
<form onSubmit={this.handleSubmit}>
{formElements}
</form>
</div>
</div>
);
}
});
无需在 ProjectContainer
或 ProjectPanel
中保存本地状态。 'active' 状态通过 props 流向这些组件。
我没有在您的 handleSubmit
按钮中放置任何代码,因为我觉得您那里的内容最初没有意义。您只需要在提交时 运行 想要的任何代码。
this.setState
允许回调函数,如果你需要在状态完全改变后做一些事情。
语法应如下所示:
switchSubmit: function(event) {
event.stopPropagation();
this.setState({
active: event.currentTarget.checked
}, this.handleSubmit);
},
我有两个组件。一个项目容器和一个项目设置面板(以后会有更多的项目设置面板)。
我在面板内有一个开关调用 "switchSubmit" 函数来更新状态,然后调用 "handleSubmit" 函数,该函数包含一个根据开关按钮的值更新 Flux Store 的操作,我正在设置状态,但它似乎始终是调用我的操作时选择的先前值。
我读到 setState 不是同步的,我也看过一些示例,但不知道如何应用正确的调用和函数来设置状态,并在调用操作时准备好更新后的状态我正在编写的这段代码。
这是我的代码:
var React = require('react/addons');
var Actions = require('../../Actions');
var ConfigurationStore = require('../../stores/Configuration');
var Controller = React.createClass({
getInitialState: function () {
ConfigurationStore.reset();
Actions.getConfigurationSettings();
return this.getStateFromStores();
},
getStateFromStores: function () {
return {
configuration: ConfigurationStore.getState()
};
},
componentDidMount: function () {
ConfigurationStore.addChangeListener(this.onStoreChange);
},
componentWillUnmount: function () {
ConfigurationStore.removeChangeListener(this.onStoreChange);
},
onStoreChange: function () {
this.setState(this.getStateFromStores());
},
render: function () {
return (
<section className="section-settings container">
<h1 className="page-header">Projects</h1>
<div className="row">
<div className="col-sm-12">
<div className="row">
<div className="col-sm-3">
</div>
<div className="col-sm-9">
<h2>Project Settings</h2>
<hr />
<ProjectContainer data={this.state.configuration} />
</div>
</div>
</div>
</div>
</section>
);
}
});
var ProjectContainer = React.createClass({
getInitialState: function () {
return {
active: false
};
},
componentWillReceiveProps: function (nextProps) {
this.setState({
active: nextProps.data.active
});
},
render: function () {
return (
<div>
<ProjectPanel data={this.props.data}></ProjectPanel>
</div>
);
}
});
var ProjectPanel = React.createClass({
getInitialState: function () {
return {
active: false
};
},
componentWillReceiveProps: function (nextProps) {
this.setState({
active: nextProps.data.active
});
},
handleSubmit: function () {
Actions.updateConfigurationSettings({
active: this.state.active
});
},
switchSubmit: function(event) {
event.stopPropagation();
this.setState({
active: event.currentTarget.checked
});
this.handleSubmit();
},
render: function() {
var formElements = (
<fieldset>
<SwitchButton
name="switch-1"
onChange={this.switchSubmit}
checked={this.props.active}
/>
</fieldset>
);
}
return (
<div className="project-holder">
<div className="project-config">
<form onSubmit={this.handleSubmit}>
{formElements}
</form>
</div>
</div>
);
}
});
如有任何帮助,我们将不胜感激!
为了直接回答您的问题,setState
接受一个回调,该回调可用于将代码推迟到渲染完成之后。但是,您不需要在您的方案中使用它。
我在您的代码中看到的问题是您有多个 'active' 状态的真实来源。
我已更新您的代码以解决该问题:
var React = require('react/addons');
var Actions = require('../../Actions');
var ConfigurationStore = require('../../stores/Configuration');
var Controller = React.createClass({
getInitialState: function () {
ConfigurationStore.reset();
Actions.getConfigurationSettings();
return this.getStateFromStores();
},
getStateFromStores: function () {
return {
configuration: ConfigurationStore.getState()
};
},
componentDidMount: function () {
ConfigurationStore.addChangeListener(this.onStoreChange);
},
componentWillUnmount: function () {
ConfigurationStore.removeChangeListener(this.onStoreChange);
},
onStoreChange: function () {
this.setState(this.getStateFromStores());
},
render: function () {
return (
<section className="section-settings container">
<h1 className="page-header">Projects</h1>
<div className="row">
<div className="col-sm-12">
<div className="row">
<div className="col-sm-3">
</div>
<div className="col-sm-9">
<h2>Project Settings</h2>
<hr />
<ProjectContainer data={this.state.configuration} />
</div>
</div>
</div>
</div>
</section>
);
}
});
var ProjectContainer = React.createClass({
render: function () {
return (
<div>
<ProjectPanel data={this.props.data}></ProjectPanel>
</div>
);
}
});
var ProjectPanel = React.createClass({
handleSubmit: function () {
// Do something interesting on submit.
},
switchSubmit: function(event) {
event.stopPropagation();
Actions.updateConfigurationSettings({
active: event.target.checked
});
},
render: function() {
var formElements = (
<fieldset>
<SwitchButton
name="switch-1"
onChange={this.switchSubmit}
checked={this.props.data.active}
/>
</fieldset>
);
}
return (
<div className="project-holder">
<div className="project-config">
<form onSubmit={this.handleSubmit}>
{formElements}
</form>
</div>
</div>
);
}
});
无需在 ProjectContainer
或 ProjectPanel
中保存本地状态。 'active' 状态通过 props 流向这些组件。
我没有在您的 handleSubmit
按钮中放置任何代码,因为我觉得您那里的内容最初没有意义。您只需要在提交时 运行 想要的任何代码。
this.setState
允许回调函数,如果你需要在状态完全改变后做一些事情。
语法应如下所示:
switchSubmit: function(event) {
event.stopPropagation();
this.setState({
active: event.currentTarget.checked
}, this.handleSubmit);
},