I'm creating a mobile navigation menu and using CSSTransition component from React Transition Group to handle animating in the different levels of my navigation.
I am able to successfully animate in different levels but only in one direction. For instance, the content will enter in from the right and exit to the left. The part that is confusing to me is when i need to change the direction that the content animates in or out.
For my example lets say I have 3 slides
Initially slide #2 would enter in from the right If we go to slide #3 it would exit left.
If we are on slide #3 and want to go back to slide #2 then I want slide #2 to enter in from the right.
import { useState } from 'react';
import { CSSTransition } from 'react-transition-group';
import './App.css';
const App = () => {
const [page, setPage] = useState(1);
return (
<>
Page: {page}
<nav>
<button onClick={() => page !== 1 && setPage(page - 1)}>Prev</button>
<button onClick={() => page >= 1 && page <= 2 && setPage(page 1)}>
Next
</button>
</nav>
<div className='content'>
<CSSTransition
in={page === 1}
classNames='slide'
timeout={500}
unmountOnExit
>
<SlideOne />
</CSSTransition>
<CSSTransition
in={page === 2}
classNames='slide'
timeout={500}
unmountOnExit
>
<SlideTwo />
</CSSTransition>
<CSSTransition
in={page === 3}
classNames='slide'
timeout={500}
unmountOnExit
>
<SlideThree />
</CSSTransition>
</div>
</>
);
};
const SlideOne = () => {
return <h3>Hello From Slide One</h3>;
};
const SlideTwo = () => {
return <h3>Hello From Slide Two</h3>;
};
const SlideThree = () => {
return <h3>Hello From Slide Three</h3>;
};
export default App;
.content {
width: 200px;
height: 100px;
overflow: hidden;
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.1);
padding: 1rem;
position: relative;
}
h3 {
position: absolute;
}
.slide-enter {
opacity: 0;
transform: translateX(100%);
}
.slide-enter-active {
opacity: 1;
transform: translateX(0%);
transition: all 0.5s;
}
.slide-exit {
opacity: 1;
transform: translateX(0%);
}
.slide-exit-active {
opacity: 0;
transform: translateX(-100%);
transition: all 0.5s;
}
CodePudding user response:
import { useState } from "react";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import "./App.css";
const App = () => {
const [page, setPage] = useState(1);
const [direction, setDirection] = useState("left");
return (
<>
Page: {page}
<nav>
<button
onClick={() => {
page !== 1 && setPage(page - 1);
direction !== "right" && setDirection("right");
}}
>
{" "}
Prev
</button>
<button
onClick={() => {
page >= 1 && page <= 2 && setPage(page 1);
direction !== "left" && setDirection("left");
}}
>
Next
</button>
</nav>
<div className="content">
{/* <TransitionGroup> */}
<CSSTransition
in={page === 1}
classNames={`slide-${direction}`}
timeout={500}
unmountOnExit
>
<SlideOne />
</CSSTransition>
<CSSTransition
in={page === 2}
classNames={`slide-${direction}`}
timeout={500}
unmountOnExit
>
<SlideTwo />
</CSSTransition>
<CSSTransition
in={page === 3}
classNames={`slide-${direction}`}
timeout={500}
unmountOnExit
>
<SlideThree />
</CSSTransition>
{/* </TransitionGroup> */}
</div>
</>
);
};
const SlideOne = () => {
return <h3>Hello From Slide One</h3>;
};
const SlideTwo = () => {
return <h3>Hello From Slide Two</h3>;
};
const SlideThree = () => {
return <h3>Hello From Slide Three</h3>;
};
export default App;
.content {
width: 200px;
height: 100px;
overflow: hidden;
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.1);
padding: 1rem;
position: relative;
}
h3 {
position: absolute;
}
.slide-left-enter {
opacity: 0;
transform: translateX(100%);
}
.slide-left-enter-active {
opacity: 1;
transform: translateX(0%);
transition: all 2000ms;
}
.slide-left-exit {
opacity: 1;
transform: translateX(0%);
}
.slide-left-exit-active {
opacity: 0;
transform: translateX(-100%);
transition: all 2000ms;
}
.slide-right-enter {
opacity: 0;
transform: translateX(-100%);
}
.slide-right-enter-active {
opacity: 1;
transform: translateX(0%);
transition: all 2000ms;
}
.slide-right-exit {
opacity: 1;
transform: translateX(0%);
}
.slide-right-exit-active {
opacity: 0;
transform: translateX(100%);
transition: all 2000ms;
}
the trick is to reverse the translation on every key button