如果我在函数中间更新状态,函数其余部分的执行顺序是什么?

If I update state in the middle of a function, what will be the execution order for the rest of the function?

我正在使用 Context API 和带有钩子的 React 功能组件。我有一个功能组件 ProfileForm.js

在这个文件的顶部,我调用了 useContext,这样我就可以访问当前状态(一组配置文件对象)。

const {state: {userProfiles}, addProfile, removeProfile, editProfile} = useContext(UserProfilesContext);

对于这个例子,我将重点关注函数 addProfile。当用户单击提交按钮时,我想将新配置文件添加到全局 state/context 并且我想将更新后的列表保存到 AsyncStorage.

这是我的处理程序:

const saveProfileHandler = async(profiles) = >
{
    const {
        firstName, lastName, userPhone, userEmail, userMonth, userDay, userYear,
        userStreet, userCity, userState, userZip,
    }
    = formState.inputValues;

    Keyboard.dismiss();

    if (validateForm()) {
        let month = userMonth;
        let day = userDay;
        if (month.length == = 1) {
            month = `0 $ { userMonth }
            `;
        }
        if (day.length == = 1) {
            day = `0 $ { userDay }
            `;
        }

        const profile = new UserProfile(
            firstName.trim(),
            lastName.trim(),
            userPhone.trim(),
            userEmail.trim(),
            month.trim(),
            day.trim(),
            userYear.trim(),
            userStreet.trim(),
            userCity.trim(),
            userState.trim(),
            userZip.trim(), );

        // add profile to Context object
        addProfile(profile);

        await saveUserProfilesToStorage([... profiles, profile ]);

        navigation.pop();
    }
};

当我调用 addProfile 时,我更新了全局 state/context,所以我知道 React 将重新渲染我的组件。所以,我真的有 2 个问题:

  1. 依赖我刚刚保存的全局状态值是不是不安全。我的意思是,我可以使用更新后的上下文状态并将其保存到 AsyncStorage 中,还是它还没有更新因此不可靠?
  2. 在我调用 addProfile 之后,函数的其余部分是在从状态更新重新渲染之前继续 运行,还是 addProfile 导致组件在之前重新渲染其余的功能完成了吗?如果它确实在函数调用的中间重新呈现,那么函数的其余部分何时执行?

提前致谢。

这就是我能够学到的东西。我会把它放在这里供偶然发现它的其他人使用。

要知道在React中setState()是一个异步函数很重要。 JavaScript引擎由内存堆和调用栈组成。调用堆栈将 运行 所有同步函数。 JavaScript 引擎旁边是 Web API(由浏览器提供)和事件循环(回调队列)。

当一个函数被执行时,它被放置在调用堆栈上并且同步开始执行。如果您从当前 运行ning 函数内部调用另一个函数,新函数将获得自己的执行上下文。当前函数将暂停执行,新函数将执行完成(假设在其上下文中没有新函数调用)并且 return 控制将继续执行的第一个函数。

异步事件

浏览器 Web API 环境中的异步代码 运行s。这可以防止代码阻塞 JavaScript thread/call 堆栈。异步代码的回调函数在 Web API 环境中注册。当回调准备好执行时,它被放入回调队列中。所有回调,除了那些 return 承诺的回调,都在这里排队。

直到调用堆栈为空时才会执行回调。然后将以 FIFO(先进先出)顺序执行。

同样重要的是要知道来自 promises 的回调(then, catch)不会被放入回调队列中。他们进入微任务队列。该队列优先于回调队列。这意味着微任务队列中的所有回调都将在回调队列的任务之前被调用。


在我的例子中,上下文更新将在 navigation.pop(); 之后发生,但由于上下文是全局的,我不会在组件卸载后更新 UI,所以应该没问题。

如有错误,欢迎指正。