CSS-переходы не сохраняются. Компонент React меняет внутреннюю структуру DOM

Я проиллюстрировал проблему в этом CodePen

const Component = ({ structure }) => {
  switch (structure) {
    case 'nested': 
      return (
        <div>
          <AnimatedComponent />
      </div>
     );
    case 'flat': 
      return 
        <AnimatedComponent />
      ;
  }
};

В AnimatedComponent есть некоторая логика, которая меняет стиль компонента в анимированном виде, например. изменить цвет фона с черного на красный в течение 1 секунды. Анимация запускается изменением класса цвета на AnimatedComponent. Существует CSS для обработки анимации с учетом измененного класса.

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

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

Это возможно?

Я пытался использовать реквизит key для <AnimatedComponent />, но он исправляет только вспышку изменения DOM. Анимация пропущена. См. Codepen. Спасибо Thomas Rooney за это предложение.

Могу ли я сказать React применить изменения класса всего через один тик после изменения позиции элемента DOM?


person Tobias Mühl    schedule 05.06.2016    source источник


Ответы (1)


Могу ли я сказать React применить изменения класса всего через один тик после изменения позиции элемента DOM?

Да, именно для этого и предназначена функция setTimeout. Копирование вашего второго примера, в котором вы исправили мерцание, обернув отправку цветового действия с помощью setTimeout (без значения времени, которое по умолчанию равно 0), кажется, решает вашу проблему.

onColorClick: () => {
  setTimeout(() => { 
    dispatch({type: 'TOGGLE_COLOR'})
  })
},

codepen

Обновление: я заметил, что немного надежнее добавить некоторое время перед изменением цвета (второй аргумент в setTimeout, (fn, ms). Я считаю, что это потому, что setState также происходит асинхронно.

onColorClick: () => {
  setTimeout(() => { 
    dispatch({type: 'TOGGLE_COLOR'})
  }, 100) <-- play around with this value
},
person azium    schedule 05.06.2016
comment
Это работает как задумано! Есть только ошибка, но это не имеет значения для моей проблемы. Когда вы находитесь во вложенном состоянии и нажимаете кнопку change both 2 раза подряд, в поле 2 загорается цветная вспышка. - person Tobias Mühl; 05.06.2016
comment
Я бы не сказал, что это ошибка, поскольку так работает анимация CSS3 — ее нельзя прервать. Если вы ищете что-то более гибкое, загляните на github.com/chenglou/react-motion - person azium; 05.06.2016
comment
Я просто устал. Что ж, мы просто откладываем изменения состояния/реквизита. Не думаю, что это может заменить **переход... - person DevBear15; 10.07.2017