Javascript/react — переключение свойств двух объектов в массиве в состоянии реакции без запуска повторного рендеринга

Мне просто нужно заменить ключи одного объекта массива другим. Я приведу обоснование того, почему я *думаю, что мне нужно сделать это позже, чтобы попытаться избежать 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}`}
  />
)

При включении сторонней библиотеки в компонент React часто необходимо предотвратить обновление с помощью shouldComponentUpdate и позволить стороннему коду обновляться самостоятельно.

Emile Bergeron 18.07.2019 20:52

Что ж, его нужно обновлять, такие вещи, как «проп isInteractable», управляются родителем. Но я также говорю, что весь компонент перемонтируется, потому что изменяется массив, отображающий каждый элемент. Думаю, именно это и меняет позиции.

mheavers 18.07.2019 20:56
shouldComponentUpdate давайте фильтровать, что должно обновляться, а что нет. Кроме того, если у стороннего поставщика есть единственный экземпляр, который вообще не следует повторно инициализировать, вам следует выполнить обновление вручную, передав новые значения стороннему экземпляру через их API.
Emile Bergeron 18.07.2019 20:59

Я говорю «сторонний», но это может быть ваш собственный холст, iframe и т. д. Вы не обязаны использовать React для обновления, просто рекомендуется свести ручные обновления к минимуму.

Emile Bergeron 18.07.2019 21:01

Да, интересно, следует ли мне использовать нереагирующую версию библиотеки, чтобы у меня был доступ к свойству z-index вместо того, чтобы менять массив вокруг... это действительно все, что мне нужно сделать.

mheavers 18.07.2019 21:22

Убедитесь, что вы правильно используете атрибут key. лучше использовать какой-нибудь id для canvasImage для установки ключа. Использование index внутри ключа — плохой подход. Именно поэтому он переустанавливается.

lavrton 19.07.2019 05:17
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
6
202
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как я вижу, вы используете 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}
  />
)

Другие вопросы по теме