Мне просто нужно заменить ключи одного объекта массива другим. Я приведу обоснование того, почему я *думаю, что мне нужно сделать это позже, чтобы попытаться избежать TLDR, на случай, если кто-то обнаружит более глубокую причину, по которой мне вообще не нужно этого делать.
Итак, дано:
canvasImages = [
{
property1: 1
property2: 2
},
{
property1: 3,
property2: 4,
}
]
Я хочу указать два объекта в массиве и перебрать их свойства (поскольку список свойств может быть длинным) и сказать (псевдокод):
canvasImages[1].property1 = canvasImages[2].property1;
canvasImages[2].property2 = canvasImages[2].property2;
etc...
в минимально возможном коде.
ОБОСНОВАНИЕ:
Я использую реакцию с библиотекой холста, где два перетаскиваемых объекта холста из массива в состоянии необходимо переключить порядок z, не вызывая повторного рендеринга из реакции (иначе холст теряет память о том, куда перетаскивались объекты...).
Итак, когда я попытался просто сделать:
const {canvasImages} = this.state;
const oldIndex = 1; const newIndex = 2;
const reorderedCanvasImages = reorderArray(canvasImages,oldIndex,newIndex) //unshown function, just reorders the array
this.setState({
canvasImages: reorderedCanvasImages //this triggers a re-mount of the URLImage component
});
или:
const newCanvasImages = _.clonedeep(canvasImages);
const oldIndex = 1; const newIndex = 2;
const reorderedCanvasImages = reorderArray(canvasImages,oldIndex,newIndex)
this.state.canvasImage[0] = newCanvasImages[0];
this.state.canvasImage[1] = newCanvasImages[1];
эти canvasImages теряют любую перетаскиваемую позицию:
canvasImages.map((canvasImage, index) => {
//remounted after setState on canvasImages or even after changing array positions within this.state.canvasImages
return (
<URLImage
src = {`${canvasImage.image}`}
isInteractable = {activeCanvasImageIndex === index}
className = {`canvas__interactable`}
key = {`canvas__interactable--${canvasImage.object}_${index}`}
/>
)
Что ж, его нужно обновлять, такие вещи, как «проп isInteractable», управляются родителем. Но я также говорю, что весь компонент перемонтируется, потому что изменяется массив, отображающий каждый элемент. Думаю, именно это и меняет позиции.
shouldComponentUpdate
давайте фильтровать, что должно обновляться, а что нет. Кроме того, если у стороннего поставщика есть единственный экземпляр, который вообще не следует повторно инициализировать, вам следует выполнить обновление вручную, передав новые значения стороннему экземпляру через их API.
Я говорю «сторонний», но это может быть ваш собственный холст, iframe и т. д. Вы не обязаны использовать React для обновления, просто рекомендуется свести ручные обновления к минимуму.
Да, интересно, следует ли мне использовать нереагирующую версию библиотеки, чтобы у меня был доступ к свойству z-index вместо того, чтобы менять массив вокруг... это действительно все, что мне нужно сделать.
Убедитесь, что вы правильно используете атрибут key
. лучше использовать какой-нибудь id
для canvasImage
для установки ключа. Использование index
внутри ключа — плохой подход. Именно поэтому он переустанавливается.
Как я вижу, вы используете index
и объект внутри ключевого атрибута:
key = {`canvas__interactable--${canvasImage.object}_${index}`}
Когда вы переупорядочиваете объекты, у вас будут совершенно НОВЫЕ ключи, отличные от старых. В этом случае React считает, что это новые компоненты, поэтому удаляет старые и создает новые. Чтобы избежать этого, просто используйте uniq id
для каждого элемента в массиве:
const canvasImages = [
{
id: 1,
property1: 1
property2: 2
},
{
id: 2,
property1: 3,
property2: 4,
}
]
canvasImages.map((canvasImage, index) => {
return (
<URLImage
src = {`${canvasImage.image}`}
isInteractable = {activeCanvasImageIndex === index}
className = {`canvas__interactable`}
key = {canvasImage.id}
/>
)
При включении сторонней библиотеки в компонент React часто необходимо предотвратить обновление с помощью
shouldComponentUpdate
и позволить стороннему коду обновляться самостоятельно.