Reputation: 3
I have started playing with react-transition-group and have managed to create some pretty good animations. However, I am struggling to create dynamic animations based on user interactions.
I believe the issue might be caused by the transition executing before the state is set to a different value. Essentially, when switching from one animation to another, the entering part of the animation seems to use the previous animation's settings. However, when I click the same button again, it works correctly.
For simplicity, I created a basic React application to illustrate my problem. Below is the code I am using:
JSX:
import Card from './modules/Card';
import './App.css';
import { useEffect, useState, useRef } from 'react';
import { SwitchTransition, CSSTransition } from 'react-transition-group';
function App() {
const [index, setIndex] = useState(1);
const transitionRef = useRef(false);
useEffect(() => {
console.log(index);
}, [index]);
function handleNext(event) {
transitionRef.current = false;
setIndex((prevIndex) => prevIndex + 1);
}
function handlePrev(event) {
if (index > 1) {
transitionRef.current = true;
setIndex((prevIndex) => prevIndex - 1);
}
}
return (
<div className="motherDiv">
<div>
<button onClick={handleNext}>Next</button>
<button onClick={handlePrev}>Prev</button>
</div>
<div className="transitionGroup">
<SwitchTransition mode="out-in">
<CSSTransition
key={index}
timeout={1000}
classNames={transitionRef.current ? 'slideReverse' : 'slide'}
>
<Card index={index} key={index} />
</CSSTransition>
</SwitchTransition>
</div>
</div>
);
}
export default App;
CSS:
.motherDiv {
display: flex;
width: 100%;
height: 100%;
justify-content: space-around;
align-items: center;
flex-direction: column;
}
.transitionGroup {
position: relative;
}
/* Normal Slide */
/* slide enter */
.slide-enter {
opacity: 0;
transform: translate3d(100%, 0, 0);
z-index: 1;
}
.slide-enter-active {
opacity: 1;
transform: translate3d(0%, 0, 0);
transition: opacity 1000ms, transform 1000ms;
}
/* slide exit */
.slide-exit {
opacity: 1;
transform: translate3d(0%, 0, 0);
position: absolute;
top: 0;
}
.slide-exit-active {
opacity: 0;
transform: translate3d(-100%, 0, 0);
transition: opacity 1000ms, transform 1000ms;
}
.slide-exit-done {
opacity: 0;
}
/* Reverse Slide */
/* slideReverse enter */
.slideReverse-enter {
opacity: 0;
transform: translate3d(-100%, 0, 0);
z-index: 1;
}
.slideReverse-enter-active {
opacity: 1;
transform: translate3d(0%, 0, 0);
transition: opacity 1000ms, transform 1000ms;
}
/* slideReverse exit */
.slideReverse-exit {
opacity: 1;
transform: translate3d(0%, 0, 0);
position: absolute;
top: 0;
}
.slideReverse-exit-active {
opacity: 0;
transform: translate3d(100%, 0, 0);
transition: opacity 1000ms, transform 1000ms;
}
.slideReverse-exit-done {
opacity: 0;
}
The card component is just a card with an image and a paragraph that displays the current index.
Upvotes: 0
Views: 19