【问题标题】:setState is not permanentsetState 不是永久的
【发布时间】:2019-04-03 06:28:49
【问题描述】:

我正在尝试创建一个具有可折叠选项的侧边菜单。

下面是我的代码:

export default class CRSideMenu extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      fprActive: true
    };
    autoBind(this);
  }

  toggleFPR() {
    console.log('Setting fprActive from ', this.state.fprActive, ' to ', !this.state.fprActive);
    this.setState({
      fprActive: !this.state.fprActive
    });
  }

  render() {
    console.log('render', this.state.fprActive);
    return (
      <ul className='list-group list-group-nav'>
        <li>
          <a 
            href='#' 
            className={classnames('list-group-item', this.state.fprActive && 'active', 'has-subnav')}
            onClick={this.toggleFPR} >
            FPR
          </a>
          <ul className='list-group list-group-nav'>
            <li>
              <a href='' className='list-group-item'>FR</a>
            </li>
          </ul>
        </li>
      </ul>
    );
  }
}

当我在 render() 方法中打印出 this.state.fprActive 时,我看到以下内容:

  • 将 fprActive 从 true 设置为 false
  • 渲染错误
  • 真实呈现

当我只点击一次时,为什么我的 fprActive 会自动设置为“true”?

【问题讨论】:

  • 我假设autoBind 使toggleFDR 绑定到this

标签: javascript reactjs render setstate


【解决方案1】:

我无法在此重现该问题,但症状表明当您单击锚点时您的页面正在刷新,因为您没有阻止默认操作。让toggleFPR 在它收到的事件对象上调用preventDefault

toggleFPR(event) {
//        ^^^^^ ------------ ***
  event.preventDefault(); // ***
  console.log('Setting fprActive from ', this.state.fprActive, ' to ', !this.state.fprActive);
  this.setState({
    fprActive: !this.state.fprActive
  });
}

另外:你在这里打破了the fundamental React rules 之一:

console.log('Setting fprActive from ', this.state.fprActive, ' to ', !this.state.fprActive);
this.setState({
  fprActive: !this.state.fprActive
});

根据现有状态设置状态时,您必须使用回调版本,而不是您将对象传入的版本:

this.setState(({fprActive}) => {
  console.log('Setting fprActive from ', fprActive, ' to ', !fprActive);
  return {fprActive: !fprActive};
});

如果您不这样做,它会在大部分时间工作,但有时会以难以诊断的方式失败。

【讨论】:

  • 这完美!我注意到,当我将 标记换成
    标记时,没有页面重新呈现(没有 event.preventDefault())。似乎在引擎盖下 标签被称为
  • @AKJ - 我在答案末尾添加了一条注释,您的 setState 调用违反了 React 的基本规则之一,因此您需要修复它。编码愉快!
  • 非常感谢您对代码的改进。我能知道({fprActive}) 是从哪里来的吗?我也做了这些改变,但我想理解它而不是盲目复制:)
  • @AKJ - 参数列表中的 destructuringsetState 的回调版本将当时的状态对象作为其参数。在参数列表中使用{fprActive} 只需要它的fprActive 属性。顺便说一句,我很高兴这能奏效,因为我无法单独复制这个问题...... :-)
  • 换句话说,如果我在构造函数的`this.state = {...}`中有其他属性(比如attr1和attr2),我也可以这样做:this.setState(({fprActive, attr1, attr2}) =&gt; {...}); ?
猜你喜欢
  • 2012-08-26
  • 1970-01-01
  • 1970-01-01
  • 2015-07-03
  • 2019-02-25
  • 2015-03-08
  • 1970-01-01
  • 2021-11-02
  • 1970-01-01
相关资源
最近更新 更多