Если я обновлю состояние в середине функции, каков будет порядок выполнения для остальной части функции?

#react-native #state-management #context-api

Вопрос:

Я использую контекстный API и реагирую на функциональные компоненты с помощью крючков. У меня есть функциональный компонент ProfileForm.js

В верхней части этого файла я вызываю useContext, чтобы получить доступ к текущему состоянию (массив объектов профиля).

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

В этом примере я сосредоточусь на функции addProfile . Когда пользователь нажимает кнопку «Отправить», я хочу добавить новый профиль в глобальное состояние/контекст и сохранить обновленный список 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 , я обновляю глобальное состояние/контекст, поэтому я знаю, что React повторно отобразит мой компонент. Итак, у меня действительно есть 2 вопроса:

  1. Небезопасно полагаться на значение глобального состояния, которое я только что сохранил. Я имею в виду, могу ли я использовать обновленное состояние контекста и сохранить его в AsyncStorage или оно еще не будет обновлено и, следовательно, ненадежно?
  2. После того, как я вызову addProfile , будет ли остальная часть функции продолжать выполняться до повторного отображения из обновления состояния или addProfile приведет к повторному отображению компонента до завершения остальной части функции? Если он повторно отображается в середине вызова функции, когда выполняется остальная часть функции?

Заранее спасибо.

Ответ №1:

Это то, чему я смог научиться. Я помещу его здесь для тех, кто на него наткнется.

Важно знать, что в React setState() является асинхронной функцией. Движок JavaScript состоит из кучи памяти и стека вызовов. Стек вызовов будет выполнять все синхронные функции. Рядом с движком JavaScript находятся веб-API (предоставляемые браузером) и Цикл событий (очередь обратного вызова).

Когда функция выполняется, она помещается в стек вызовов, и выполнение начинается синхронно. Если вы вызовете другую функцию из текущей запущенной функции, новая функция получит свой собственный контекст выполнения. Текущая функция приостановит выполнение, новая функция будет выполняться до завершения (при условии, что в ее контексте не будет вызовов новых функций) и вернет управление первой функции, которая продолжит выполнение.

Асинхронные События

Асинхронный код выполняется в среде веб-API браузера. Это предотвращает блокировку кода потоком/стеком вызовов JavaScript. Функции обратного вызова для асинхронного кода регистрируются в среде веб-API. Когда обратный вызов готов к выполнению, он помещается в очередь обратного вызова. Все обратные вызовы, за исключением тех, которые возвращаются обещаниями, помещаются здесь в очередь.

Обратные вызовы не будут выполняться до тех пор, пока стек вызовов не опустеет. затем они будут выполняться в порядке FIFO (первый вход, первый выход).

Также важно знать, что обратные вызовы от обещаний (затем, catch) не помещаются в очередь обратного вызова. Они попадают в очередь микрозадач. Эта очередь имеет приоритет над очередью обратного вызова. Это означает, что все обратные вызовы из очереди микрозадач будут вызываться до задач очереди обратного вызова.


В моем случае обновление контекста произойдет после navigation.pop(); , но поскольку контекст является глобальным, и я не обновляю пользовательский интерфейс после отключения компонента, все должно быть в порядке.

Если я в чем-то ошибаюсь, я приветствую исправления.