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

React CSSTransition切换页面时重复创建新页面并执行过渡问题排查

问题分析与修复方案

核心问题

你的实现存在两个关键错误,导致页面过渡行为异常:

  1. 错误地将<Routes>整体包裹在<CSSTransition>内
    React Router v6的<Routes>组件会根据location变化直接替换内部渲染的路由组件,旧页面会被立即卸载,<TransitionGroup>无法跟踪其退出动画。同时,这种结构会触发<CSSTransition>重复渲染新路由组件——因为location.key更新时,整个<Routes>会被重新挂载,导致新页面被创建两次。

  2. 未让<TransitionGroup>管理单个路由元素的进出
    <TransitionGroup>的设计目标是跟踪单个元素的挂载/卸载状态,从而执行过渡动画。而你让它包裹整个路由匹配容器<Routes>,违背了这个使用逻辑,无法实现新旧页面的平滑交替。

修复后的代码

调整结构,使用useRoutes获取当前匹配的单个路由元素,再交由<CSSTransition>和<TransitionGroup>管理:

import "./styles.css";
import "bootstrap/dist/css/bootstrap.min.css";
import { BrowserRouter, useLocation, useNavigate, useRoutes } from "react-router-dom";
import { TransitionGroup, CSSTransition } from "react-transition-group";
import { Nav, Navbar } from "react-bootstrap";
import Settings from "./Settings";
import TestPage from "./TestPage";

function App() {
  const location = useLocation();
  const navigate = useNavigate();

  // 通过useRoutes获取当前匹配的路由元素
  const currentRouteElement = useRoutes([
    { path: "/settings", element: <Settings /> },
    { path: "/testPage", element: <TestPage /> },
  ]);

  return (
    <div className="App">
      <Navbar collapseOnSelect expand="lg" bg="dark" variant="dark">
        <Navbar.Brand href="#home">Blaa</Navbar.Brand>
        <Navbar.Toggle aria-controls="responsive-navbar-nav" />
        <Navbar.Collapse id="responsive-navbar-nav">
          <Nav className="mr-auto">
            <Nav.Link onClick={() => navigate("/settings")}>Settings</Nav.Link>
            <Nav.Link onClick={() => navigate("/testPage")}>TestPage</Nav.Link>
          </Nav>
        </Navbar.Collapse>
      </Navbar>
      <TransitionGroup component={null}>
        <CSSTransition key={location.key} classNames="fade" timeout={3000}>
          {/* 仅渲染当前匹配的单个路由组件 */}
          {currentRouteElement}
        </CSSTransition>
      </TransitionGroup>
    </div>
  );
}

const Root = () => (
  <BrowserRouter basename={window.location.pathname.replace(/(/[^/]+)$/, "")}>
    <App />
  </BrowserRouter>
);

export default Root;

补充CSS要求

确保你的styles.css中包含完整的过渡类样式,保证动画正常执行:

.fade-enter {
  opacity: 0;
}
.fade-enter-active {
  opacity: 1;
  transition: opacity 3000ms ease-in;
}
.fade-exit {
  opacity: 1;
}
.fade-exit-active {
  opacity: 0;
  transition: opacity 3000ms ease-out;
}
.fade-exit-done {
  display: none;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 02:16:13