在 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})
}
编辑:
将函数转换为生成器函数。
如果用户按下“+'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})
}
编辑: 将函数转换为生成器函数。