我制作了一个通过xhr加载数据的组件,用户选择< select>的值元件。
class SomeComponent extends Component {
state = {
data: [],
currentCategory: 'all'
}
switchCategory = (ev) => {
console.log('Selected category is ' + ev.target.value);
this.setState({
currentCategory: ev.target.value
});
this.loadData();
}
loadData = async () => {
let { currentCategory } = this.state;
// Always print previous value!!!
console.log(currentCategory);
// Get data via XHR...
}
render() {
return (
<div>
<select value={currentCategory} onChange={this.switchCategory}>
<option value="all">All</option>
{categories.map( category =>
<option key={category._id} value={category.category}>{category.display}</option>
)}
</select>
<table>
// ... prints data with this.state.data
</table>
</div>
);
}
}
上面的代码只是简单的说明。代码非常简单,我只是将select元素的值与this.state.currentCategory同步,并使用该类的switchCategory方法检测它的切换。
但主要的问题是当我访问组件的状态时,它总是包含先前的值,而不是当前的值。您可以看到我在选择更改的值上更新currentCategory。
switchCategory = (ev) => {
console.log('Selected category is ' + ev.target.value);
this.setState({
currentCategory: ev.target.value
});
this.loadData();
}
所以在这种情况下,this.state.currentCategory必须没有“all”,就像其他“Apple”一样,但它仍然包含“all”,而不是“Apple”!
loadData = async () => {
let { currentCategory } = this.state;
// Always print previous value!!! I expected "Apple", but it has "all"
console.log(currentCategory);
// Get data via XHR...
}
所以最终XHR发生了以前的值,它给了我错误的数据,这是我没想到的。 之后,选择其他值的选择(让我们称之为香蕉),它有一个苹果,而不是香蕉!
我知道setState是“sync”作业,因此在更新状态后调用this.switchCategory会发生,因此它必须具有当前值,而不是之前的值。
但是当我在控制台中打印组件的状态时,它不是。
那么,我错过了什么?为什么我总是得到旧数据,不存在?如果我采取了错误的做法,那么我可以做些什么选择呢?
任何建议都会非常感激。谢谢!
答案 0 :(得分:2)
这里的问题是setState
是异步的(在某些情况下可以同步)。这就是为什么你得到以前的价值。
有两种可能的解决方案。
//
// 1. use value directly.
//
switchCategory = (ev) => {
this.setState({ currentCategory: ev.target.value });
this.loadData(ev.target.value);
}
loadData = async (currentCategory) => {
console.log(currentCategory);
// Get data via XHR...
}
//
// 2. use completition callback on `setState`.
//
switchCategory = (ev) => {
this.setState({ currentCategory: ev.target.value }, () => {
this.loadData(ev.target.value);
});
}
loadData = async () => {
const { currentCategory } = this.state;
console.log(currentCategory);
// Get data via XHR...
}
关于React [link]
中同步setState
的文章