You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

react-router-dom v6.3 结合framer-motion实现路由切换过渡效果的问题咨询

解决React Router v6 + Framer Motion路由切换动画不生效的问题

我刚好处理过相同的场景,把React Router从v5升级到v6后,原来的路由过渡动画直接失效了,下面是我验证可行的解决方案:

核心问题分析

React Router v6的Routes组件要求直接子元素只能是Route,所以不能像v5那样把motion.div包在路由容器外面——那样所有页面共享同一个motion容器,自然只会在首次加载时触发一次动画。我们需要让每个路由页面都拥有独立的motion容器,这样切换时旧容器卸载触发exit动画,新容器挂载触发enter动画。

具体实现步骤

  1. 首先确保引入所需的API(注意v6里用Navigate替代v5的Redirect):
import { Routes, Route, Navigate, useLocation } from 'react-router-dom';
import { AnimatePresence, motion } from 'framer-motion';
  1. 保留你原来的动画配置:
const pageVariants = { 
  initial: { opacity: 0 }, 
  in: { opacity: 1 }, 
  out: { opacity: 0 } 
}; 
const pageTransition = { type: 'tween', ease: 'linear', duration: 0.5 };
  1. 在组件内获取当前location,然后调整路由结构:
const YourApp = () => {
  const location = useLocation();

  return (
    <AnimatePresence mode="wait">
      <PageLayout>
        {/* 必须把location传给Routes,让AnimatePresence能感知路由变化 */}
        <Routes location={location}>
          {/* 每个路由的element都用motion.div单独包裹 */}
          <Route 
            path="/audit" 
            element={
              <motion.div
                initial="initial"
                animate="in"
                exit="out"
                variants={pageVariants}
                transition={pageTransition}
              >
                <Audit />
              </motion.div>
            } 
          />
          <Route 
            path="/smartx" 
            element={
              <motion.div
                initial="initial"
                animate="in"
                exit="out"
                variants={pageVariants}
                transition={pageTransition}
              >
                <SmartX />
              </motion.div>
            } 
          />
          <Route 
            path="/smartx/erc20" 
            element={
              <motion.div
                initial="initial"
                animate="in"
                exit="out"
                variants={pageVariants}
                transition={pageTransition}
              >
                <TokenGenerator />
              </motion.div>
            } 
          />
          <Route 
            path="/createAudit" 
            element={
              <motion.div
                initial="initial"
                animate="in"
                exit="out"
                variants={pageVariants}
                transition={pageTransition}
              >
                <PaymentStatus />
              </motion.div>
            } 
          />
          <Route 
            path="/faq" 
            element={
              <motion.div
                initial="initial"
                animate="in"
                exit="out"
                variants={pageVariants}
                transition={pageTransition}
              >
                <FAQ />
              </motion.div>
            } 
          />
          <Route 
            path="/support" 
            element={
              <motion.div
                initial="initial"
                animate="in"
                exit="out"
                variants={pageVariants}
                transition={pageTransition}
              >
                <Support />
              </motion.div>
            } 
          />
          <Route 
            path="/terms" 
            element={
              <motion.div
                initial="initial"
                animate="in"
                exit="out"
                variants={pageVariants}
                transition={pageTransition}
              >
                <Terms />
              </motion.div>
            } 
          />
          <Route 
            path="/policy" 
            element={
              <motion.div
                initial="initial"
                animate="in"
                exit="out"
                variants={pageVariants}
                transition={pageTransition}
              >
                <Policy />
              </motion.div>
            } 
          />
          <Route 
            path="/about" 
            element={
              <motion.div
                initial="initial"
                animate="in"
                exit="out"
                variants={pageVariants}
                transition={pageTransition}
              >
                <About />
              </motion.div>
            } 
          />
          {/* v6用Navigate替代Redirect */}
          <Route path="/" element={<Navigate to="/audit" />} />
        </Routes>
      </PageLayout>
    </AnimatePresence>
  );
};

关键细节说明

  • AnimatePresence的mode="wait":确保旧页面的退出动画完全结束后,再开始新页面的进入动画,避免页面切换时的动画重叠。
  • 给Routes传入location:让AnimatePresence能够准确检测到路由路径的变化,从而触发对应的动画生命周期。
  • 每个路由独立包裹motion.div:这样每次路由切换时,旧的motion容器会被卸载(触发exit动画),新的容器挂载时触发initial和animate动画,完美复刻v5时的效果。

内容的提问来源于stack exchange,提问作者user18472307

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 18:12:27