路由跳转动画:v6实现方案
React Router v6的升级之路,让我踩了不少坑。最近项目从v5升级到v6,其中路由动画的实现成了重头戏。
问题背景
在v5中,我们使用<TransitionGroup>和<CSSTransition>来实现路由切换动画,但v6移除了这些组件。迁移过程中,我尝试了多种方案,最终找到了可行的实现方式。
核心实现方案
方案一:使用useNavigate + CSS过渡
import { useNavigate, useLocation } from 'react-router-dom';
import { useEffect, useRef } from 'react';
function AnimatedRoutes() {
const navigate = useNavigate();
const location = useLocation();
const prevLocation = useRef(location);
useEffect(() => {
// 监听路由变化,添加动画类
const currentPath = location.pathname;
const prevPath = prevLocation.current.pathname;
if (currentPath !== prevPath) {
document.body.classList.add('route-transition');
setTimeout(() => {
document.body.classList.remove('route-transition');
}, 300);
}
prevLocation.current = location;
}, [location]);
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
);
}
方案二:自定义动画组件
import { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
function AnimatedRoute({ children, location }) {
const [isAnimating, setIsAnimating] = useState(false);
useEffect(() => {
setIsAnimating(true);
const timer = setTimeout(() => setIsAnimating(false), 300);
return () => clearTimeout(timer);
}, [location]);
return (
<div className={`route-wrapper ${isAnimating ? 'animate' : ''}`}>
{children}
</div>
);
}
避坑指南
- v6中
<Route>组件不再支持component属性,需使用element替代 useHistory已废弃,改用useNavigate- 动画性能优化要注意避免重绘和回流
最终效果
通过合理运用CSS transition配合useNavigate钩子,成功在v6中实现了平滑的路由切换动画。虽然过程有些曲折,但最终效果还是很满意的。

讨论