反应setState并等待 [英] React setState and await

查看:59
本文介绍了反应setState并等待的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尽管在使用当前状态时建议使用功能setState(),但该功能仍不能异步.我们如何开发一个使用状态的函数,调用REST API,然后立即更改状态?

While the functional setState() is recommended when the current state is being used, the function still cannot be async. How could we develop a function that uses the state, calls a REST API and changes the state right after?

这是原始功能,无视setState的异步行为.

This is the original function, that disregards the async behavior of 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只能在异步函数中使用.

If we change the above function to use functional setState, VSCode complains that await can only be used in async functions.

onSortColumnChanged = (sortColumn) => (event) => {
    this.setState((prev) => {
​        const searchParams = { ...prev.params, sortColumn: sortColumn };
​        const result = await this.callSearch(searchParams);
​        return { params: searchParams, result: result };
    });
}

我想我这里缺少一些基本知识.

I think I'm missing something fundamental here.

推荐答案

简短答案

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
    })
}

长答案

为什么要使用setState回调

React文档指出可能多次调用setState

Long answer

Why use setState callbacks

The React docs state that multiple calls to setState may be batched together.

假装您有一个聊天应用程序.您可能具有如下所示的功能:

Let's pretend you have a chat app. You might have a function that looks like this:

async incoming_message(message){
    this.setState({messages: this.state.messages.concat(message)})
}

因此,如果两条消息相隔几毫秒,React可以将这两个调用分批处理到 setState()

So if 2 messages come in a few milliseconds apart, React may batch these two calls to setState()

this.setState({messages: [].concat(message_1)}) // 1
this.setState({messages: [].concat(message_2)}) // 2

,当 2 运行时,我们将丢失 message_1 .

and when 2 runs, we will lose message_1.

为setState提供转换功能是解决方案

Providing setState with a transform function is the solution

async incoming_message(message){
    this.setState(prev => {
        prev.messages.push(message)
        return prev
    })
}

在基于回调的setState中,第一条消息不会丢失,因为我们指定了一种将旧状态转换为新状态的方法,而不是指定要写入的确切状态.

In the callback-based setState, the 1st message will not be lost, since instead of specifying an exact state to write, we specify a way to transform the old state into the new state.

setState()的对象版本对新状态和先前状态进行浅表合并.这意味着用对象调用 setState()更新您传入的密钥.

The object version of setState() does a shallow merge of the new state and the previous state. This means that calling setState() with an object will only update the keys that you pass in.

如果您选择使用 setState()的回调版本,则应返回整个新状态.因此,当您拥有

If you choose to use the callback version of setState() instead, you are expected to return the entire new state. So when you have

return { params: searchParams, result: result };

在您的 setState()回调中,您将丢失除 params result 之外的所有状态值.

in your setState() callback, you will lose all state value except params and result.

在使用当前状态时建议使用功能性setState()

the functional setState() is recommended when the current state is being used

了解为什么建议使用功能性 setState()很重要.如果将多个 setState()调用一起批处理时代码不会中断,则可以传递一个对象而不是一个函数.

It is important to understand why the functional setState() is recommended. If your code will not break when multiple setState() calls are batched together, it is OK to pass an object instead of a function.

如果您仍想使用回调模式,则无需在 setState()回调中完成所有工作,只需指定如何将旧状态转换为新的.

If you still want to use the callback pattern, you don't need to do all the work in your setState() callback, you only need to specify how to transform the old state into the new one.

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,
        }) 
    })
}

这篇关于反应setState并等待的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆