虽然在使用当前状态时建议使用函数setState(),但该函数仍然不能是异步的。我们如何开发一个使用状态的函数,调用REST API并在之后立即更改状态?
这是原始函数,它忽略了setState的异步行为。
onSortColumnChanged = (sortColumn) => async (event) => {
const prev = this.state;
const searchParams = { ...prev.params, sortColumn: sortColumn };
const result = await this.callSearch(searchParams);
this.setState({ params: searchParams, result: result });
}
如果我们将上述函数更改为使用函数setState,VSCode会抱怨await只能在异步函数中使用。
onSortColumnChanged = (sortColumn) => (event) => {
this.setState((prev) => {
const searchParams = { ...prev.params, sortColumn: sortColumn };
const result = await this.callSearch(searchParams);
return { params: searchParams, result: result };
});
}
我想我在这里缺少一些基本的东西。
答案 0 :(得分:2)
onSortColumnChanged = (sortColumn) => async (event) => {
const searchParams = { ...this.state.params, sortColumn: sortColumn };
const result = await this.callSearch(searchParams);
this.setState(prev => {
prev.params.sortColumn = sortColumn
prev.result = result
return prev
})
}
The React docs表示可以对setState进行多次调用。
让我们假装您有一个聊天应用。您可能有一个如下所示的函数:
async incoming_message(message){
this.setState({messages: this.state.messages.concat(message)})
}
因此,如果两条消息相隔几毫秒,则React可以将这两个调用批处理为setState()
this.setState({messages: [].concat(message_1)}) // 1
this.setState({messages: [].concat(message_2)}) // 2
当2
投放时,我们将失去message_1
。
为setState提供转换函数是解决方案
async incoming_message(message){
this.setState(prev => {
prev.messages.push(message)
return prev
})
}
在基于回调的setState中,第一条消息不会丢失,因为我们没有指定要写入的确切状态,而是指定了一种将旧状态转换为新状态的方法。
setState()
的对象版本对新状态和先前状态进行浅层合并。这意味着,使用对象调用setState()
将仅更新您传入的密钥。
如果您选择使用setState()
的回调版本,则需要返回整个新状态。所以,当你有
return { params: searchParams, result: result };
在您的setState()
回调中,您将失去除params
和result
以外的所有州值。
当使用当前状态时,建议使用函数setState()
了解为什么推荐功能性setState()
非常重要。如果多个setState()
调用一起批处理时代码不会中断,则传递对象而不是函数是可以的。
如果您仍想使用回调模式,则不需要在setState()
回调中完成所有工作,您只需指定如何将旧状态转换为新状态。
onSortColumnChanged = (sortColumn) => async (event) => {
const {params} = this.state;
const searchParams = { ...params, sortColumn: sortColumn };
const result = await this.callSearch(searchParams);
this.setState(prev => {
// prev is the old state
// we changed sortColumn param
prev.params.sortColumn = sortColumn
// and we changed the result
prev.result = result
// and we return the new, valid state
return prev
// or if you prefer an immutable approach
return Object.assign({}, prev, {
params: {...prev.params, sortColumn: sortColumn},
result: result,
})
})
}
答案 1 :(得分:1)
将'await'视为promise的回调函数。所以你在这里没有承诺,你正在调用回调函数。因此,VSCode要求您添加承诺,在这种情况下它是“异步”功能。