Home > Mobile >  React Transition Group Dynamically Change Slide Direction
React Transition Group Dynamically Change Slide Direction

Time:03-26

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

  • Related