Search code examples
javascriptreactjsreact-routerreactcsstransitiongrouppage-transition

React CSSTransition when you change page by Route


I'm using CSSTransition and it works amazing with components:

<CSSTransition timeout={330} in={state.isPopupOpen} classNames="popup" unmountOnExit>
    <MyComponent />
</CSSTransition>

I was wondering if I can use CSSTransition to have a nice transition when I open/close a page by Route:

<BrowserRouter>
    <Switch>
        <Route path="/page1">
            <CSSTransition timeout={330} in={state.isPageOpen} classNames="page" unmountOnExit>
                <Page1 />
            </CSSTransition>
        </Route>
        <Route path="/page2">
            <Page2 />
        </Route>
    <Switch>
</BrowserRouter>

<Link to="/page1">Link example</Link>

I tried it without any success. Is it not possible using CSSTransition in this way? Do you have another similar solution?


Solution

  • Thanks to @xadm's comment I tested a useful solution on https://css-tricks.com/animating-between-views-in-react/

    However with React Router v6 I found a easier solution with a different library called Framer Motion (https://www.framer.com/motion/).

    Same result, less effort summarized in a snippet of code

    import { AnimatePresence } from 'framer-motion'
    import { BrowserRouter, Routes, Route, Link, useLocation } from "react-router-dom";
    
    import { motion } from 'framer-motion'
    
    const PageTransition = (props) => {
      return (
        <motion.div
          {...props}
          initial={{ opacity: 0, x: '50vw' }}
          animate={{ opacity: 1, x: 0 }}
          exit={{ opacity: 0, x: '-50vw' }}
          style={{ position: 'fixed', top: 0, left: 0, width: '100%', height: '100%' }}
          transition={{ type: 'tween', duration: .3 }}
        >
          {props.children}
        </motion.div>
      )
    }
    
    const Page1 = (props) => {
      return (
        <PageTransition>
          <h3>Page 1</h3>
          <Link to="/page2">Go to Page 2</Link>
        </PageTransition>
      );
    }
    
    const Page2 = (props) => {
      return (
        <PageTransition>
          <h3>Page 2</h3>
          <Link to="/">Go to Page 1</Link>
        </PageTransition>
      );
    }
    
    const AnimatedRoutes = () => {
      const location = useLocation();
    
      return (
        <AnimatePresence exitBeforeEnter>
          <Routes location={location} key={location.pathname}>
            <Route path="/" element={<Page1 />} />
            <Route path="/page2" element={<Page2 />} />
          </Routes>
        </AnimatePresence>
      );
    };
    
    function App() {
    
      return (
        <BrowserRouter>
          <AnimatedRoutes />
        </BrowserRouter>
      );
    
    }
    
    export default App;