Как изменить порядок компонентов при сохранении состояния? - PullRequest
4 голосов
/ 17 июня 2020

Сценарий

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

Проблема

При изменении порядка состояние одного подкомпонента попадает в другой. В качестве примера предположим, что на первом рендере у меня есть подкомпоненты A и B в указанном порядке. При следующем рендеринге порядок меняется на B и A. Состояние, которое было в A, теперь находится в B, и наоборот.

Я сделал более простой пример в Code Sandbox , чтобы проиллюстрируйте ситуацию. Список сохраняет тот же порядок, хотя при следующем рендеринге он меняется на противоположный.

Я полагаю, это связано с тем, как React поддерживает состояние в разных компонентах, в котором порядок хуки имеют значение.

Должен ли React разобраться с этим сценарием? Проблема в моем коде? Если да, каким должен быть правильный способ повторного рендеринга компонентов в другом порядке?

1 Ответ

1 голос
/ 17 июня 2020

Это связано с тем, как react обрабатывает элементы в своей виртуальной DOM.

Решение: Добавьте ключ, и он будет работать.

<StatefulComponent param={"Tomato"} key={"Tomato"} />,
<StatefulComponent param={"Potato"} key={"Potato"}/>

Почему происходит такое поведение?

По умолчанию, если ключ не указан, response предоставит каждому компоненту в списке ключ со значением порядка индекса, в котором он был изначально отрисован - вот что вызывает проблему. Поскольку вы не определили идентификатор, React неявно превращает ваши компоненты в это:

<StatefulComponent param={"Tomato"} key={0} />,
<StatefulComponent param={"Potato"} key={1}/>

И после массива reverse():

<StatefulComponent param={"Potato"} key={0} />,
<StatefulComponent param={"Tomato"} key={1}/>

Причина, по которой вы видите неожиданное поведение связано с тем, что react использует ключи для идентификации каждого элемента. Итак, если вы измените порядок массива после исходной визуализации, а затем примените индекс в качестве идентификатора для каждой визуализации, response получит элемент, который был сначала визуализирован с этим индексом в качестве ключа, и поместит его в это место. Изменяя ключ на уникальный идентификатор, react не смешивает элементы (поскольку уникальный идентификатор никогда не изменяется по отношению к его элементу) и теперь может точно отображать каждый элемент в том порядке, который вы намереваетесь.

Пример : Мы визуализируем список:

<div id=1>Foo</div> // Id "1" is now bound to this element
<div id=2>Bar</div>

Итак, если вы затем переупорядочите список следующим образом (обратите внимание на изменения идентификатора):

<div id=1>Bar</div> // this will be transformed to <div id=1>Foo</div>
<div id=2>Foo</div> // this will be transformed to <div id=2>Bar</div>

Тогда response преобразует элементы в любой идентификатор, который они были назначены первыми - вот почему важно иметь уникальных идентификаторов .

Вы можете прочитать больше здесь: https://medium.com/@robinpokorny / index-as-a-key-is- an-anti-pattern-e0349aece318

...