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

如何正确配置react-transition-group实现嵌套路由独立动画?

解决React Router嵌套路由动画被外层覆盖的问题

这个问题不是react-transition-group不支持嵌套路由动画,而是你的动画作用范围和CSS优先级导致的冲突——外层的CSSTransition把整个嵌套组件都包裹在了它的fade动画容器里,当路由切换时,外层的fade动画会先触发,并且它的CSS规则会覆盖内层zoom动画的样式。下面给你两种可行的解决方案:

方案1:给顶层路由单独添加动画(推荐)

不要用CSSTransition包裹整个外层Switch,而是给每个顶层路由的组件单独包裹CSSTransition。这样外层动画只会作用于顶层路由的内容,嵌套路由的动画容器是独立的,不会被覆盖:

import { useLocation, Switch, Route, NavLink } from "react-router-dom";
import { CSSTransition } from "react-transition-group";

function AnimationApp() {
  const location = useLocation();
  return (
    <div className="app-container">
      <nav>
        <NavLink to="/">Home</NavLink>
        <NavLink to="/nested">Nested Routes</NavLink>
      </nav>
      <Switch location={location}>
        {/* 给每个顶层路由单独加fade动画 */}
        <Route path="/nested">
          <CSSTransition key={location.key} classNames="fade" timeout={500}>
            <Nested />
          </CSSTransition>
        </Route>
        <Route path="/">
          <CSSTransition key={location.key} classNames="fade" timeout={500}>
            <Home />
          </CSSTransition>
        </Route>
      </Switch>
    </div>
  );
}

function Nested() {
  const location = useLocation();
  return (
    <div className="nested-container">
      <nav>
        <NavLink to="/nested/sub1">Sub Page 1</NavLink>
        <NavLink to="/nested/sub2">Sub Page 2</NavLink>
      </nav>
      {/* 嵌套路由的zoom动画正常使用 */}
      <CSSTransition key={location.key} classNames="zoom" timeout={500}>
        <Switch location={location}>
          <Route path="/nested/sub1">
            <SubPage title="Sub Page 1" />
          </Route>
          <Route path="/nested/sub2">
            <SubPage title="Sub Page 2" />
          </Route>
          <Route path="/nested">
            <NestedHome />
          </Route>
        </Switch>
      </CSSTransition>
    </div>
  );
}

方案2:提高嵌套动画的CSS优先级

如果你坚持要在外层用CSSTransition包裹整个Switch,可以通过增强嵌套动画CSS选择器的优先级来覆盖外层样式:

/* 外层fade动画样式 */
.fade-enter {
  opacity: 0;
}
.fade-enter-active {
  opacity: 1;
  transition: opacity 500ms;
}
.fade-exit {
  opacity: 1;
}
.fade-exit-active {
  opacity: 0;
  transition: opacity 500ms;
}

/* 嵌套zoom动画样式,通过父容器选择器提高优先级 */
.nested-container .zoom-enter {
  transform: scale(0.9);
  opacity: 0;
}
.nested-container .zoom-enter-active {
  transform: scale(1);
  opacity: 1;
  transition: transform 500ms, opacity 500ms;
}
.nested-container .zoom-exit {
  transform: scale(1);
  opacity: 1;
}
.nested-container .zoom-exit-active {
  transform: scale(0.9);
  opacity: 0;
  transition: transform 500ms, opacity 500ms;
}

这种方法虽然可行,但不如第一种方法清晰,容易引发后续的CSS优先级问题,所以更推荐方案1。

总结一下:react-transition-group完全支持嵌套路由动画,你的问题是动画作用范围的设计导致的样式覆盖,调整动画的包裹范围或者CSS优先级就能解决。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 15:47:55