我有一个tempAddList,它将包含一个ID列表,我将把状态设置到relInfo表中,并回调addRelation函数以提交数据。但是,例如当我运行onAddClick时,如果tempAddList = [2,3,4] 它会使用最新的setState id 4运行addRelation 3次,但不会运行2和3。我如何让它针对每个单独的id运行。
final String url = "http://api.azanpro.com/times/today.json?zone=ngs02&format=12-hour";
List data;
Future<String> getSWData() async {
var res = await http
.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
setState(() {
var resBody = json.decode(res.body);
data = resBody["prayer_times"];
});
答案 0 :(得分:1)
将this.state
与setState
一起使用是一种反模式。因为状态更新是异步的,所以这可能导致争用情况。这是updater function的用例。
几次setState
调用将导致批量更新,其中addRelation
处于最新更新状态。
一种解决方法是不要批量更新,而要等待状态更新,例如with await
:
async onAddClick = () => {
const setStateAsync = updater => new Promise(resolve => this.setState(updater, resolve));
for (const id of this.state.tempAddList) {
await setStateAsync(state => ({
relInfo: {
...state.relInfo,
modId: id
}
});
this.addRelation();
});
};
一个更好的解决方案是不依赖于副作用的状态更新(addRelation
)。 state
的目的是在render
中使用。如果状态更新不影响视图(仅显示最新的modId
更新),则不需要:
onAddClick = () => {
let { relInfo } = this.state;
this.state.tempAddList.forEach((id) => {
relInfo = { ...relInfo, modId: id };
this.addRelation(relInfo);
});
this.setState({ relInfo });
};
addRelation = (relInfo) => {
EdmApi.insertModifier(relInfo);
};
如果modId
中未使用render
,则可以将其从状态中排除。在这种特定情况下,缺少更新程序功能应该不是问题,因为单击处理程序是异步触发的,它们不太可能通过干扰状态更新而导致竞争状态。