我在load()
/ async
函数和React中更改状态时遇到问题。
这是我的异步功能,该功能是通过单击按钮触发的:
await
在此函数中,我使用async startNewEntry() {
this.addIssue();
let issue_id;
console.log(this.state.timeEntry, "started_timeEntry")
if (this.state.timeEntry?.issue?.id) {
issue_id = this.state.timeEntry?.issue?.id;
} else {
issue_id = (await this.issueService.list()).data[0]?.id;
}
const { data } = await this.timeEntryService.create({
comments: this.state.timeEntry.comments,
issue_id,
spent_on: moment(new Date()).format("YYYY-MM-DD"),
hours: 0.01,
activity_id: this.localStorageService.get("defaultActivityId")
});
,并使用this.addIssue
,这会更改类的组件状态:
this.createIssue
如您所见,在我的异步函数中,我第一次拥有新的状态,但实际上异步函数在我的addIssue() {
this.projectService.list([]).then(response => {
response.data = response.data.filter((x: any) => x.status === 1);
this.setState(
{
activeProjects: response.data
},
() => {
this.createIssue();
}
);
});
}
createIssue() {
this.issueAddService
.create({
project_id: this.state.activeProjects[0].id,
tracker_id: trakerId,
priority_id: priorityId,
subject: this.state.timeEntry.comments,
description: this.state.timeEntry.comments
})
.then(response => {
let timeEntry = this.state.timeEntry;
timeEntry.issue = response.data;
this.setState({
timeEntry
});
})
.catch(error => {
console.log("error", error);
});
}
函数之前起作用。我知道这个问题可能有点古怪,但是谢谢前进!
答案 0 :(得分:2)
如果您希望startNewEntry
等到addIssue
完成工作之后,您需要:
addIssue
返回完成工作后的承诺,并且await
:await this.addIssue();
如果您需要startNewEntry
来查看更新后的状态,则需要从状态完成处理程序回调中履行addIssue
的承诺,如下所示:
addIssue() {
// *** Return the promise chain to the caller
return this.projectService.list([]).then(response => {
response.data = response.data.filter((x: any) => x.status === 1);
// *** Create a new promise
return new Promise(resolve => {
this.setState(
{
activeProjects: response.data
},
() => {
this.createIssue();
resolve(); // *** Fulfill the promise
}
);
});
});
}
new Promise
通常是一种反模式,尤其是当您有另一个可以从中进行承诺的承诺时。但是在这种情况下,由于您需要等待来自setState
的回调(未启用Promise),因此是合适的。 (
请注意my comment。我认为您正在建立一个无限循环...
答案 1 :(得分:1)
我不是React专家,但是我不完全理解为什么在这个地方有很多setState
调用。
如果将setState
留在函数的末尾,则可能不必担心对异步调用的正确排序(尽管其他答案确实显示了如何实现)。
也许一次调用它可能会使代码更清晰。我欢迎更正...
async startNewEntry() {
const activeProjects = await fetchActiveProjects()
const issue = await this.createIssue()
const timeEntry = await createTimeEntry({ issue, comments: this.state.timeEntry.comments })
this.setState({ activeProjects, issue, timeEntry })
}
async fetchActiveProjects() {
const { data } = await this.projectService.list([])
return data.filter(({ status }) => status === 1)
}
async createIssue() {
const { data } = await this.issueAddService.create({
project_id: this.state.activeProjects[0].id,
tracker_id: trakerId,
priority_id: priorityId,
subject: this.state.timeEntry.comments,
description: this.state.timeEntry.comments
})
return data
}
async createTimeEntry({issue, comments}) {
const { data } = await this.timeEntryService.create({
comments,
issue_id: issue?.id || (await this.issueService.list()).data[0]?.id,
spent_on: moment(new Date()).format("YYYY-MM-DD"),
hours: 0.01,
activity_id: this.localStorageService.get("defaultActivityId")
})
return data
}
您可以通过并行化前两个异步调用来进一步加快速度:
async startNewEntry() {
const [activeProjects, issue] =
await Promise.all([fetchActiveProjects(), this.createIssue()])
const timeEntry = await createTimeEntry({ issue, comments: this.state.timeEntry.comments })
this.setState({ activeProjects, issue, timeEntry })
}