Состояние реакции очищается между вызовами в функции обратного вызова - PullRequest
0 голосов
/ 24 января 2020

У меня есть эта функция:

addMessages(productId) {
    const msg = "Some message about product: " + productId;
    const newMessages = [...this.state.messages, msg];
    console.log(this.state.messages);
    this.setState({messages: newMessages}, function () {
        console.log(newMessages);
        console.log(this.state.messages);
    });
}

И я вызываю ее дважды

for (i = 700; i <= 701, i++) {
    addMessages(i);
}

И я получаю этот вывод:

[]
[]
["Some message about product: 700"]
["Some message about product: 701"]
["Some message about product: 701"]
["Some message about product: 701"]

Кто-нибудь знает почему мое состояние ведет себя так странно? Сначала я понимаю, что это пустой массив и что он дважды проходит через первый оператор консоли, прежде чем у него появится шанс go внутри функции обратного вызова. Но почему мой штат не получает 700? И почему между вызовами его опустошают?

1 Ответ

1 голос
/ 24 января 2020

Происходит то, что setState является асинхронным и реагирует на обновления состояния пакетной обработки. Реагирует на документы о setState пакетировании .

Два console.log вне обратного вызова setState выполняются немедленно во время l oop. Затем следующие два исходят из первого setState обратного вызова, а последние два исходят из второго setState обратного вызова.

Причина, по которой их выходные данные кажутся странными, заключается в том, что newMessages фактически каждый раз отличается , но this.state.messages уже был обновлен в обоих обратных вызовах. Причина этого заключается в том, как реагирует пакетное обновление состояния. Чтобы проиллюстрировать это, вы можете консоль регистрации внутри функции render и увидеть, что реакция только инициировала 1 повторный рендеринг для 2 обновлений состояния.

В итоге React пакетирует ваш setStates и оба обратных вызова выполняются после всех ваших зацикленных обновлений.

Также Примечание: Поскольку вы создаете новый массив состояний на основе предыдущих значений, вам следует использовать форму обновления setState. В настоящее время this.state.messages будет пустым массивом для каждой итерации. Форма обновления гарантирует, что вы будете использовать самую последнюю копию состояния для обновления.

Попробуйте вместо создания newMessages вне вызова обновления:

this.setState(prevState => ({ messages: [...prevState.messages, msg] }), /*callback*/ )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...