reactjsreact-routercss-transitionsreact-transition-groupreactcsstransitiongroup

I cannot get React Transition Group to work. No enter or leave transitions


Hi I cannot get React Transition Group working at all. Can anyone take a look at this and see why it will not work? The links pull in the components correctly but there are no transitions. No transition coming in or going out and the console.log doesn't fire. I do get a depreciation warning in console but everything is up to date and I'm not sure if that would cause it to stop working or not. I am at a loss so any help would be really appreciated. Thank you.

import * as React from 'react'
import {
    HashRouter as Router,
    Link,
    Switch,
    Route,
    Redirect,
    useParams,
    useLocation
} from "react-router-dom";
import {TransitionGroup, CSSTransition} from "react-transition-group";


const TransGroup = () =>{

    const location = useLocation();

    return(
        <>
            <div className={"w-full h-full"}>
        <Router>
            <div className={"fill w-full"}>

                <ul className={"nav overflow-hidden mb-8 flex "}>
                    <li><Link className={"bg-white p-8 m-8 text-black inline-block"} to={"/"}>Red</Link></li>
                    <li><Link className={"bg-white p-8 m-8 text-black inline-block"} to={"/purple"}>Purple</Link></li>
                    <li><Link className={"bg-white p-8 m-8 text-black inline-block"} to={"/blue"}>Blue</Link></li>
                    <li><Link className={"bg-white p-8 m-8 text-black inline-block"} to={"/yellow"}>Yellow</Link></li>
                    <li><Link className={"bg-white p-8 m-8 text-black inline-block"} to={"/pink"}>Pink</Link></li>
                    <li><Link className={"bg-white p-8 m-8 text-black inline-block"} to={"/aqua"}>Aqua</Link></li>

                </ul>
            </div>
        </Router>
        <div className={"fill content w-full h-full"}>
            <TransitionGroup>
                <CSSTransition
                    timeout={5000}
                
                    onEnter={() => {
                        console.log('FIRED!');
                    }}
                    classNames={{
                        appear: 'my-node-appear',
                        appearActive: 'my-node-active-appear',
                        appearDone: 'my-node-done-appear',
                        enter: 'my-node-enter',
                        enterActive: 'my-node-active-enter',
                        enterDone: 'my-node-done-enter',
                        exit: 'my-node-exit',
                        exitActive: 'my-node-active-exit',
                        exitDone: 'my-node-done-exit',
                    }}
                    key={location.key}

                >
            <Switch location={location}>
                <Route exact path={"/"}>
                 
                    <div className={"bg-red-500 text-white w-full h-16"}>
                        RED
                    </div>
                </Route>
                <Route exact path={"/purple"}>
                   
                    <div className={"bg-lcnuk-other text-white w-full h-16"}>
                        PURPLE
                    </div>
                </Route>
                <Route exact path={"/blue"}>
                 
                    <div className={"bg-blue-500 text-white w-full h-16"}>
                        BLUE
                    </div>
                </Route>
                <Route exact path={"/yellow"}>
                 
                    <div className={"bg-lcnuk-other text-white w-full h-16"}>
                        YELLOW
                    </div>
                </Route>
                <Route exact path={"/pink"}>
                 
                    <div className={"bg-white text-black w-full h-16"}>
                        PINK
                    </div>
                </Route>
                <Route exact path={"/aqua"}>
                
                    <div className={"bg-black text-white w-full h-16"}>
                        AQUA
                    </div>
                </Route>
                <Route path={'*'}>
                    <div>Not Found</div>
                </Route>
            </Switch>
                </CSSTransition>
            </TransitionGroup>
        </div>
            </div>
        </>
    )
}
export default TransGroup

Solution

  • When using CSSTransition for routes, you don't want to use a Switch or a TransitionGroup. You want to put the CSSTransition in each route individually, and then each route will need it's own ref and you need to pass the ref to the nodeRef prop of the CSSTransition node.

    Here's a working example I made on Codesandbox:

    And here's the block of code that demonstrates this:

    ///...
    
    interface AppRoute {
      path: string;
      title: string;
      Component: React.ComponentType;
    }
    
    const appRoutes: AppRoute[] = [
      { path: "/", title: "Home", Component: HomePage },
      { path: "/page1", title: "Page 1", Component: Page1 },
      { path: "/page2", title: "Page 2", Component: Page2 }
    ];
    
    ///...
    
    ////// CONTENT TRANSITION ROUTER
    const PageContent = withRouter(({ location }) => {
      let routeRefs: any[] = [];
    
      const isMatch = useCallback(
        (path: string): boolean => {
          return location.pathname === path ? true : false;
        },
        [location]
      );
    
      return (
        <>
          {appRoutes.map(({ path, Component }, index) => {
            routeRefs[index] = React.useRef(null);
    
            return (
              <Route key={index} exact path={path}>
                {() => {
                  // Route callback ensures the transitions are loaded correctly
                  return (
                    <CSSTransition
                      nodeRef={routeRefs[index]}
                      in={isMatch(path)}
                      timeout={300}
                      classNames="fade"
                      unmountOnExit
                      appear
                    >
                      <div ref={routeRefs[index]} className="fade">
                        <Component />
                      </div>
                    </CSSTransition>
                  );
                }}
              </Route>
            );
          })}
        </>
      );
    });