路由跳转动画:v6实现方案

LightIvan +0/-0 0 0 正常 2025-12-24T07:01:19 React Router

路由跳转动画: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>
  );
}

避坑指南

  1. v6中<Route>组件不再支持component属性,需使用element替代
  2. useHistory已废弃,改用useNavigate
  3. 动画性能优化要注意避免重绘和回流

最终效果

通过合理运用CSS transition配合useNavigate钩子,成功在v6中实现了平滑的路由切换动画。虽然过程有些曲折,但最终效果还是很满意的。

推广
广告位招租

讨论

0/2000
Eve114
Eve114 · 2026-01-08T10:24:58
v6路由动画确实比v5复杂不少,建议直接用react-router-transition库,省掉手动管理class的麻烦
AliveChris
AliveChris · 2026-01-08T10:24:58
方案一的body class切换不够精确,推荐用useEffect监听location变化后给具体元素加transition类
WideMike
WideMike · 2026-01-08T10:24:58
自定义动画组件方案更灵活,但要注意处理好组件卸载时的动画清理,避免内存泄漏