Реагирующие компоненты контекста не будут обновляться при изменении состояния - PullRequest
0 голосов
/ 06 апреля 2020

Я пытаюсь создать провайдер контекста реакции в функциональном компоненте. Я использую ловушку useState, чтобы предоставить массив другим компонентам, и у меня есть функция add, которая помещает новое значение в массив. Массив и функция добавления предоставляются через провайдер контекста.

Похоже, что использование pu sh с перехватчиками состояний при выполнении

var newArray = array
newArray.push("text")
setArray(newArray)

не вызывает компоненты, использующие состояние для повторного отображения, но при использовании

setArray(array=> [...array, "text"])

компоненты, использующие массив, предоставленный поставщиком контекста, обновляют.

Кто-нибудь сможет объяснить, почему это так?

Ответы [ 3 ]

1 голос
/ 06 апреля 2020

Массивы изменчивы в javascript, поэтому, когда вы создаете переменную и указываете ее на массив (как в вашем примере)

var newArray = array

newArray на самом деле не скопируйте его экземпляр, вместо этого просто храните ссылку на него. Это можно увидеть в очень простом примере, сделанном в консоли браузера, который показан ниже

the browser console

Когда вы изменяете массив в своем примере, нажимая новый переменная он просто добавит его в исходный массив, изменяя состояние и не вызывая рендеринга. Когда React выполняет согласование после вызова setArray с новым массивом, он видит, что массив (ссылка) одинаков и не вызывает повторного рендеринга.

Когда вы используете пример нотации распространения, вы создаете новый массив используя [], просто синтактически c сахар для new Array и выгрузки элементов из старого в новый. Когда он сравнивает старое состояние с новым и его новыми элементами, React видит разницу и перерисовывает ваш компонент.

Если вы все же предпочтете сделать это так, как вы изначально установили, вы можете использовать Функция массива .slice () для создания нового массива с данными, существующими в вызываемом массиве, поэтому он будет var newArray = array.slice(). Если вы добавите элемент в новый массив и установите его состояние, он будет визуализирован.

0 голосов
/ 06 апреля 2020

Прочитайте о мутации состояния.

В реакции вы не должны изменять состояние для повторного рендеринга. Если вы помещаете sh объект в массив, это мутация, и она не создает новую ссылку для этой переменной состояния, и реакция не может определить, был ли он обновлен или нет. React использует поверхностное сравнение, поэтому, даже если содержимое массива различно, ссылка одинакова. Вам необходимо обновить ссылку, чтобы вызвать рендер.

0 голосов
/ 06 апреля 2020

Когда вы устанавливаете состояние с помощью оператора распространения ..., вы создаете новый объект. Если вы не используете его и устанавливаете состояние со старым объектом, React не будет обновлять ваши компоненты, поскольку свойство состояния не изменилось (ссылка на объект не изменилась). Как я сказал в начале, используя [... array], вы фактически создаете новый объект (новую ссылку), поэтому обновите состояние React.

...