The key to get it working is:
- Wrap the <Routes> element in a <AnimatePresence> element (for exit animations, when components are unmounted)
- Add key={location.pathname} location={location} to the <Routes> element
- Use a <motion.div> (or similar element) within your route (content) element
import React from "react";
import { Routes, Route, useLocation } from "react-router-dom";
import Home from "./Home";
import Contact from "./Contact";
import About from "./About";
import { AnimatePresence } from "framer-motion";
export function AnimatedRoutes(props: {}) {
const location = useLocation();
return (
<AnimatePresence>
<Routes key={location.pathname} location={location}>
<Route path="/" element={<Home />} />
<Route path="/home" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</AnimatePresence>
);
}
export function App(props: {}) {
/* HashRouter or BrowserRouter */
return (<div>
<HashRouter>
<AnimatedRoutes />
</HashRouter>
</div>)
}
import { motion, type Variants } from "framer-motion";
const animationVariants: Variants =
{
initial: { opacity: 0, transition: { duration: 0.5 } },
in: { opacity: 1, transition: { duration: 0.75, delay: 0.3 } },
}
export function MyComponent() {
return (
<motion.div initial="initial" animate="in" variants={animationVariants}>
...
</motion.div>
);
}
782400cookie-checkReact Page Animations with Framer Motion