wannepain
wannepain

Reputation: 3

Are transitions in react-transition-group executed before state (useState())?

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

Answers (0)

Related Questions