최신 React Router버전(v6)에 맞는 문법으로 페이지 전환 애니메이션을 구현한 글을 찾기 힘들어서 기록 겸 도움이 되고자 쓰는 글.

내가 아는 선에서 큰 변화로는 아래와 같음.

  • Switch 👉 Routes
  • Router 👉 BrowserRouter
  • <Route component={} /> 👉 <Route element={}>

자세한건 공식 문서로 확인 https://reactrouter.com/docs/en/v6

 

React Router | Docs Home

Declarative routing for React apps at any scale

reactrouter.com

 

페이지 전환 애니메이션 구현은 react transition group으로도 구현 가능하나 생각보다 투박한 느낌이라서 마음에 안들었다.

그래서 구글링하다 애니메이션, 제스처 오픈소스 라이브러리인 Framer Motion을 찾게 되었고, 사용이 간편하며 결과물이 매-우 마음에 들어서 좋았다.

첫 사용에는 공식문서를 확인 후 사용하자 https://www.framer.com/docs/

 

Documentation | Framer for Developers

An open source, production-ready motion library for React on the web.

www.framer.com

 

✨ 페이지 전환 애니메이션 적용 예제

Home.js

import { motion } from 'framer-motion';
import { Link } from 'react-router-dom';
import styles from '../css/Home.module.css';

function Home() {
  const transition = {
    duration: 0.7,
    ease: [0.43, 0.13, 0.23, 0.96],
  };

  const textVariants = {
    exit: { x: 100, opacity: 0, transition },
    enter: { x: 0, opacity: 1, transition: { delay: 0.3, ...transition } },
    hover: { scale: 1.1, transition },
  };

  return (
    <motion.div
      key="home"
      className={styles.background}
      initial={{ opacity: 0.5 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0.5 }}
    >
      <section className={styles.home}>
        <motion.ul
          className={styles.home_menu}
          key="home_menu"
          variants={textVariants}
          initial="exit"
          animate="enter"
          exit="exit"
        >
          <motion.li variants={textVariants} whileHover="hover">
            <Link to="/pageA">PAGE B</Link>
          </motion.li>
          <motion.li variants={textVariants} whileHover="hover">
            <Link to="/pageB">PAGE A</Link>
          </motion.li>
        </motion.ul>
      </section>
    </motion.div>
  );
}

export default Home;

Home.js에는 motion 컴포넌트를 만들고 원하는 애니메이션을 variants에 주어 동작할 수 있도록 만들었다. 

이런식으로 PageA.js, PageB.js 에도 원하는 애니메이션을 적용시킨다. 

 

Transition.js

import { AnimatePresence } from 'framer-motion';
import { Route, Routes, useLocation } from 'react-router-dom';
import '../css/Transition.css';
import PageA from '../routes/PageA';
import PageB from '../routes/PageB';
import Home from '../routes/Home';

function Transition() {
  let location = useLocation();

  return (
    <AnimatePresence>
      <Routes key={location.pathname} location={location}>
        <Route exact path="/" element={<Home />} />
        <Route path="/pageA" element={<PageA />} />
        <Route path="/pageB" element={<PageB />} />
      </Routes>
    </AnimatePresence>
  );
}

export default Transition;

AnimatePresence : 컴포넌트가 리액트 트리에서 제거될 때(unmount) 애니메이션을 실행시킨다 = exit 애니메이션을 활용할 수 있게 해주기 때문에 페이지 전환시 애니메이션이 수행된다.

AnimatePresence를 사용할 경우 direct children 컴포넌트에 key 값을 반드시 명시해야 한다! 

 

App.js

import { BrowserRouter as Router } from 'react-router-dom';
import Transition from './components/Transition';

function App() {
  return (
    <Router basename={process.env.PUBLIC_URL}>
      <Transition />
    </Router>
  );
}

export default App;

 

 

+ Recent posts