根据reactjs中的参数更改状态

时间:2018-10-17 17:03:32

标签: javascript reactjs state

我试图学习反应,并花太多时间在非常小的事情上。 我有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)

3 个答案:

答案 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/>