javascriptcssreact-transition-group

Unable to use css transitions


With below code I can have a transition but two issues

  1. the transition seem to be going the wrong way than what i defined (right to left instead of left to right).
  2. It is supposed to transition the old widget while the new one enters but it is replacing immediately the old one with the new one then the transition begins.
  3. by swapping .fadeEnterActive with .fadeExitActive I had the second issue fixed. but the entering element now starts with .fadeEnterDone className for some reasons.

Can one spot the issue?

how can i fix that enter image description here

import { useRef, useState } from "react";
import { SwitchTransition, CSSTransition } from "react-transition-group";
import PayContainer from "../payContainer";
import PersonalInfoForm from "../persnalInfoForm";
import styles from './drawer_container.module.scss'

export default function DrawerContainer() {
    const [state, setState] = useState('pay-fill');
    const payRef = useRef(null);
    const personalInfoRef = useRef(null);
    const previewRef = useRef(null);
    const nodeRef = () => {
        switch (state) {
            case 'pay-fill':
                return payRef
            case 'personalinfo-fill':
                return personalInfoRef
            case 'preview':
                return previewRef
            default:
                return null;
        }
    }

    const setActiveState = (curState: string) => {
        setState(curState)
    }

    const getWidget = () => {
        switch (state) {
            case 'pay-fill':
                return <PayContainer setState={setActiveState}/>
            case 'personalinfo-fill':
                return <PersonalInfoForm />
            case 'preview':
                    return <div>preview nigga</div>
            default:
                return <div>default</div>;
        }
    }
    return <div className="w-full h-full">
    <SwitchTransition mode={'out-in'}>
      <CSSTransition
        key={state}
        nodeRef={nodeRef()}
        addEndListener={(done: () => void) => {
          nodeRef()?.current?.addEventListener("transitionend", done, false);
        }}
        // in={focus}
        timeout={500}
        classNames={{
            enterActive: styles.fadeEnterActive,
            enterDone: styles.fadeEnterDone,
            exitActive: styles.fadeExitActive,
            exitDone: styles.fadeExitDone
          }}
      >
        <div ref={nodeRef()}  className={['w-full h-full', styles.fade].join(' ')}>
          {getWidget()}
        </div>
      </CSSTransition>
    </SwitchTransition>
  </div>;
}

styles

  .fadeEnterActive {
    opacity: 0;
    transform: translateX(-100%);
  }
  .fadeEnterDone {
    opacity: 1;
    transform: translateX(0%);
  }
  .fadeExitActive {
    opacity: 1;
    transform: translateX(0%);
  }
  .fadeExitDone {
    opacity: 0;
    transform: translateX(100%);
  }
  .fadeEnterActive,
  .fadeExitActive {
    transition: opacity 500ms, transform 500ms;
  }

  .fade {
    
  }

Solution

  • By looking at the react-transition-group documentation, I am guessing that the problem is occurring because the starting point of the transition for fade-enter and fade-exit is not defined. And also the styles of fadeEnterActive and fadeExitActive that you provided seem to be in opposite directions.

    This code should work.

    React snippet

        <SwitchTransition mode={'out-in'}>
          <CSSTransition
            key={state}
            nodeRef={nodeRef()}
            addEndListener={(done: () => void) => {
              nodeRef()?.current?.addEventListener("transitionend", done, false);
            }}
            // in={focus}
            timeout={500}
            classNames={{
                enterActive: styles.fadeEnterActive,
                enter: styles.fadeEnter,
                exitActive: styles.fadeExitActive,
                exit: styles.fadeExit
              }}
          >
            <div ref={nodeRef()}  className={['w-full h-full', styles.fade].join(' ')}>
              {getWidget()}
            </div>
          </CSSTransition>
        </SwitchTransition>
    

    Styles

      .fadeEnter {
        opacity: 0;
        transform: translateX(-100%);
      }
      .fadeEnterActive {
        opacity: 1;
        transform: translateX(0%);
      }
      .fadeExit {
        opacity: 1;
        transform: translateX(0%);
      }
      .fadeExitActive {
        opacity: 0;
        transform: translateX(100%);
      }
      .fadeEnterActive,
      .fadeExitActive {
        transition: opacity 500ms, transform 500ms;
      }