WithSpring работает неправильно, когда SharedValue является объектом

Я пытаюсь использовать SharedValue из react-native-reanimated2 для хранения объекта (позиции ящика). Объект имеет следующую форму:

boxPositions.value = {
  [boxId]: {x: 0, y: 0}
  ...
}

Моя цель — обновить объект в SharedValue, чтобы он анимировал положение определенного поля с учетом его id.

Чтобы обновить положение блока, я делаю следующее и применяю withSpring() к свойству y объекта, чтобы он анимировался:

const moveRandomBox = () => {
  const randId = Math.floor(Math.random() * boxes.length) + 1;
  boxPositions.value = {
    ...boxPositions.value,
    [randId]: {
      x: boxPositions.value[randId].x,
      y: withSpring(boxPositions.value[randId].y - 50)
    }
  };
}

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

const rStyle = useAnimatedStyle(() => {
  const boxPosition = boxPositions.value[box.id] ? ? {x: 0, y: 0};
  return {
    transform: [
      {translateX: boxPosition.x},
      {translateY: boxPosition.y} // this value should be animated
    ]
  };
}, []);

Проблема в том, что такой подход применения анимации withSpring() приводит к тому, что поле вообще не двигается при вызове moveRandomBox().

Однако, если я изменю функцию moveRandomBox(), чтобы установить позицию y на простое значение:

[randId]: {
  x: boxPositions.value[randId].x,
  y: boxPositions.value[randId].y - 50 // instead of: withSpring(boxPositions.value[randId].y - 50)
}

а затем измените хук useAnimatedStyle(), чтобы использовать метод анимации withSpring(), он работает так, как ожидалось:

return {
  transform: [
    {translateX: boxPosition.x},
    {translateY: withSpring(boxPosition.y)} // instead of just: boxPosition.y
  ]
};

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

Мой вопрос: почему первый подход к настройке анимации не работает, а второй работает? Что не так с первым подходом, который мешает ему работать? Как мне заставить работать первый подход? Кажется, я сталкиваюсь с этой проблемой только тогда, когда SharedValue является объектом, установка SharedValue для отдельного значения withSpring(), кажется, работает правильно.

Выполняемый пример: Чтобы воспроизвести, измените превью на iOS. После загрузки нажмите кнопку «Переместить случайный ящик», и вы увидите, что ни один из ящиков не перемещается. Если вы измените код для вызова withSpring() в хуке useAnimatedStyle(), как указано выше, и удалите вызов withSpring() из метода moveRandomBox(), вы увидите, что коробка движется.

Невозможно пружинить (или использовать любую другую анимацию) свойства объекта. Если вы хотите увеличить значение y, просто определите два useSharedValues. Один для вашей позиции X и один для вашей позиции Y.

Kipnoedels 12.04.2023 15:09

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

Kipnoedels 12.04.2023 15:16

Спасибо, определение двух useSharedValues() будет работать нормально, но я пытаюсь сделать это масштабируемым, скажем, если бы у меня было 10 ящиков или 100 ящиков. Я бы не хотел явно создавать переменную SharedValue для каждого. Я мог бы использовать цикл, но насколько я знаю, что не следует делать, если это действительно не нужно...?

Shnick 12.04.2023 15:29

В этом случае, не лучше ли было бы создать один повторно используемый компонент коробки, а затем зациклиться на том количестве, которое вы хотите?

Kipnoedels 12.04.2023 16:21

@Kipnoedels это на самом деле то, что я делаю (вы можете видеть в примере с закусками на выставке, у меня есть компонент Box). Я не могу поместить туда вызов useSharedValue() для создания одной переменной xPos и ​​yPos, потому что мне нужно иметь возможность контролировать положение Box вне самого компонента Box. Вот почему я вытащил логику SharedValue из самого компонента коробки и переместил ее в родительский компонент (приложение). Именно поэтому я создал объект, чтобы отслеживать положение каждой отдельной коробки.

Shnick 13.04.2023 02:23
Поведение ключевого слова "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) для оценки ваших знаний,...
0
5
70
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Основываясь на вашем комментарии, вы хотите на самом деле две проблемы.

  1. Springify значение внутри объекта.
  2. Обновите «состояние» компонентов, отображаемое из цикла.

Для первой проблемы мы уже нашли решение. Вместо пружинизации всего объекта (что невозможно из-за того, как работает реанимация), вам нужно указать значения x и y отдельно. Я не очень разбираюсь в деталях того, как работает общее значение, но оно должно быть чем-то между двумя потоками и иметь ссылки на объекты, где дочерние изменения не распознаются из-за того, как они обрабатываются/передаются.


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

Например, при использовании ScrollView вы не поднимаете все их состояния позиций до родительского, а вместо этого назначаете ref, который содержит функции, которые вы хотите вызвать. Например. scrollTo.

Это то же самое для ваших компонентов коробки. У них должно быть собственное поведение, чтобы вы могли назначить им ref и случайным образом получить одну из этих ссылок для вызова нужной вам функции. Например. moveBoxTo().

Если это не то, что вы хотите, вы можете дать каждому ящику уникальный идентификатор. Что-то вроде того, что есть у вас сейчас. Поскольку ваше «случайное» движение кажется статичным (поэтому всегда делайте то же самое). Вы можете передать «id-to-move» всем ящикам и прослушать это значение, используя useAnimatedReaction. В этом хуке вы проверяете, соответствует ли идентификатор ящика случайному идентификатору, который должен двигаться, и анимируете его положение в ожидаемую точку.

Спасибо. Использование ссылки для предоставления дочернего метода родительскому, казалось, было тем, что мне нужно (обычно я привык делать это наоборот и передавать метод от родителя дочернему). Это то, что я в итоге сделал, и я думаю, что вы имели в виду.

Shnick 13.04.2023 12:15

Хорошая работа, мне кажется!

Kipnoedels 13.04.2023 14:47

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