Reputation: 2058
I have illustrated the problem in this CodePen
const Component = ({ structure }) => {
switch (structure) {
case 'nested':
return (
<div>
<AnimatedComponent />
</div>
);
case 'flat':
return
<AnimatedComponent />
;
}
};
There's some logic in AnimatedComponent
that changes the styling of the Component in an animated fashion, e.g. change the background color from black to red over a duration of 1 second. The animation is started by changing a color class on AnimatedComponent
. There is CSS to handle the animation given the changed class.
When changing the DOM structure from nested to flat, the HTML element is destroyed and recreated, the transition starting state is lost (aka the browser doesn't know which class was set before because the element was newly created).
What I want React to do is to change the DOM structure with moving elements in new positions, not destroying and recreating them.
Is this possible?
I tried to use the key
props on <AnimatedComponent />
, but it only fixes the flash of DOM change. Animation is skipped. See Codepen. Thanks Thomas Rooney for this suggestion.
Can I tell React to apply the class changes just one tick after the position of the DOM element was changed?
Upvotes: 3
Views: 1504
Reputation: 20614
Can I tell React to apply the class changes just one tick after the position of the DOM element was changed?
Yes, this is precisely what the setTimeout
function is for. Copying your second example, where you fixed the flickering, wrapping your color action dispatch with setTimeout
(with no time value, which defaults to 0), seems to fix your issue.
onColorClick: () => {
setTimeout(() => {
dispatch({type: 'TOGGLE_COLOR'})
})
},
Update: I've noticed it's a bit more reliable to add some time before the color change (second argument in setTimeout
, (fn, ms)
. I believe this is because setState
is also happening asynchronously.
onColorClick: () => {
setTimeout(() => {
dispatch({type: 'TOGGLE_COLOR'})
}, 100) <-- play around with this value
},
Upvotes: 1