我试图学习反应,并花太多时间在非常小的事情上。 我有3个标签,突出显示哪个标签处于活动状态。不活动的选项卡旁边会显示一个数字,以使用户知道该选项卡下有多少个项目。在页面加载时,这可以正确显示,但是我希望在单击选项卡时应用这些规则。
我正在这样初始化我的状态:
this.state = {
selectedAlert: { error: false, warning: true, success: true },
}
我正在像这样渲染选项卡:
<li className="nav-item m-tabs__item" onClick={() => this.updateAlerts('error')}>
{ this.state.selectedAlert.error ? <span className="m-nav__link-badge m-badge m-badge--accent bg-danger">3</span> : null}
Errors
</li>
<li className="nav-item m-tabs__item" onClick={() => this.updateAlerts('warning')}>
{ this.state.selectedAlert.warning ? <span className="m-nav__link-badge m-badge m-badge--accent bg-warning">4</span> : null }
Warnings
</li>
<li className="nav-item m-tabs__item" onClick={() => this.updateAlerts('success')}>
{ this.state.selectedAlert.success ? <span className="m-nav__link-badge m-badge m-badge--accent bg-success">8</span> : null }
Acheivements
</li>
函数定义如下:
updateAlerts(selected){
this.setState({
selectedAlert: {error: true, warning: true, success: true,}
})
this.state.selectedAlert[selected] = false;
}
但是,当单击另一个选项卡时,无论该选项卡如何,所有通知号都会显示,并且当我在控制台日志中记录状态属性时,事情变得更加奇怪。 假设我只单击第二个选项卡,现在在函数末尾,前两个值设置为false,而我尚未单击的选项卡仍设置为true。 (即使现在所有3条通知都显示为好像都设置为true)
答案 0 :(得分:2)
您的代码如此操作的原因是因为this.setState()
是异步的,这意味着this.state.selectedAlert[selected] = false
行将在this.setState()
实际设置状态之前执行,因此this.setState()
将覆盖this.state.selectedAlert[selected] = false
设置的状态。
这就是updateAlerts
函数应如下所示的原因:
updateAlerts(selected){
this.setState({
selectedAlert: {error: true, warning: true, success: true, [selected]: false}
});
}
此外,请勿直接修改this.state
,请始终使用this.setState()
。直接更改状态可能会导致错误优化问题。反应docs说:
请不要直接更改this.state,因为之后调用setState()可能会替换您所做的更改。将此this.state视为不可变。
它实际上发生在您的代码中。 另外,这是一篇有关状态突变的好文章-https://daveceddia.com/why-not-modify-react-state-directly。
答案 1 :(得分:1)
this
在回调中起作用,必须使用绑定事件,如下例所示:
export default class Index extends React.Component
{
constructor()
{
this.state = {
selectedAlert: { error: false, warning: true, success: true },
}
this.updateAlerts = this.updateAlerts.bind(this);
}
updateAlerts(selected)
{
this.setState({
selectedAlert: {
error: (selected === 'error'),
warning: (selected === 'warning'),
success: (selected === 'success')
}
})
}
render()
{
return(.......)
}
}
希望能帮助您!
答案 2 :(得分:1)
也许您应该进行一些重构...无需跟踪状态内的所有警报类型。您可以简化很多操作,因此也可以简化updateAlerts
函数。
const ERROR = 'error';
const WARNING = 'warning';
const SUCCESS = 'success';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
selected: ERROR
};
}
render() {
const { selected } = this.state;
return (
<div>
<ul>
<li className="nav-item m-tabs__item" onClick={this.updateAlerts(ERROR)}>
{
selected !== ERROR && (
<span className="m-nav__link-badge m-badge m-badge--accent bg-danger">3</span>)
}
Errors
</li>
<li className="nav-item m-tabs__item" onClick={this.updateAlerts(WARNING)}>
{
selected !== WARNING && (
<span className="m-nav__link-badge m-badge m-badge--accent bg-warning">4</span>)
}
Warnings
</li>
<li className="nav-item m-tabs__item" onClick={this.updateAlerts(SUCCESS)}>
{
selected !== SUCCESS && (
<span className="m-nav__link-badge m-badge m-badge--accent bg-success">8</span>)
}
Achievements
</li>
</ul>
<div className="contents">
{selected === ERROR && (
<section>
ERRORS TAB ACTIVE
</section>
)}
{selected === WARNING && (
<section>
WARNING TAB ACTIVE
</section>
)}
{selected === SUCCESS && (
<section>
ACHIEVEMENTS TAB ACTIVE
</section>
)}
</div>
</div>
);
}
updateAlerts(selected) {
return () => this.setState({ selected })
}
}
ReactDOM.render(<App />, document.querySelector('main'));
ul {
border-bottom: 1px solid #444;
padding: 5px 0;
margin: 0;
}
ul li {
cursor: pointer;
display: inline-block;
margin-right: 15px;
}
ul li span {
margin-right: 5px;
}
.contents {
margin-top: 15px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<main/>