在 React JS 中更新数组时 this.setState 和 this.state 的问题

Issues with this.setState and this.state while updating an array in React JS

如果用户按下“+'button and remove the list of tables when '-”按钮,我想显示数据库中的表列表。我的代码是:

class DatabaseItem extends Component{
  constructor(){
    super();
    this.state = {
      tabList : [],
      plusIsNext : true
    };
  }

  flagOn(){
    this.setState({
      plusIsNext:!this.state.plusIsNext
    });
  }
  showTables(){
    if(this.state.plusIsNext){
      httpUtil.get(`http://localhost:4553/api?query=
      SELECT * FROM information_schema.tables WHERE table_schema='public'`,this.props.dbname).then(response => {
        this.setState({
          tabList:response.data
        })
      });
    }
    else{
      let arr = [];
      this.state.tabList = [];
      console.log(this.state.tabList);
    }
    this.flagOn();
  }
  render(){
    let sign = this.state.plusIsNext ? '+':'-';
    return(
      <div key ={this.props.dbname} >
        <button onClick ={() => {this.showTables()}}>{sign}</button><a>{this.props.dbname}</a>
        {this.state.tabList.map(table => {
          return(
            <div key = {table.table_name}>{table.table_name}</div>
          );
        })}
      </div>
    );
  }
}

现在我已经通过将空数组 [] 重新分配给 this.state.tabList 直接更新了 tabList 的值并且它有效。如果我按下特定数据库的 + 按钮表,如果我按下 - 按钮,列表就会消失。但是,如果我使用 setState 将空数组重新分配给 tabList,则 tabList 不会变空。

this.setState({
      tabList:[]
    })

let arr = [];
this.setState({
  tabList:arr
});

我是不是漏掉了什么?

我认为您的问题是 flagOn 调用。因为 JS 是异步的,所以一次最好不要多次调用 setState。发生的事情是它调用 http 请求,跳转到 flagOn 并调用 setState,然后在完成后返回请求并再次设置状态。

我通过将这些调用合并到您的条件中来重构您的代码。如果我正确理解您的代码流程,这应该可以工作!

class DatabaseItem extends Component{
  constructor(){
    super();
    this.state = {
      tabList : [],
      plusIsNext : true
    };

    this.showTables = this.showTables.bind(this)
  }

  showTables(){
    if (this.state.plusIsNext) {
      httpUtil.get(`http://localhost:4553/api?query=
      SELECT * FROM information_schema.tables WHERE table_schema='public'`,this.props.dbname).then(response => {
        this.setState({ 
          tabList: response.data,
          plusIsNext: false
        })
      });
    } else {
      this.setState({ 
        tabList: [],
        plusIsNext: true
      })
    }
  }

  render(){
    let sign = this.state.plusIsNext ? '+':'-';
    return(
      <div key ={this.props.dbname} >
        <button onClick={this.showTables}>{sign}</button><a>{this.props.dbname}</a>
        {this.state.tabList.map(table => {
          return(
            <div key = {table.table_name}>{table.table_name}</div>
          );
        })}
      </div>
    );
  }
}

我猜你应该只调用一次 setState,在你获取数据或空列表之后:

*showTables(){
  let _tabList = []
  let _plusNext = true

    if (this.state.plusIsNext) {
      yield httpUtil.get(`http://localhost:4553/api?query=
      SELECT * FROM information_schema.tables WHERE table_schema='public'`,this.props.dbname).then(response => {

          _tabList = response.data
          _plusNext = false
      });
    } 

    yield this.setState({ tabList: _tabList, plusIsNext: _plusNext})
  }

编辑: 将函数转换为生成器函数。