使用 CSSTransitionGroup 和 React-Router v6 动画路由过渡

Posted

技术标签:

【中文标题】使用 CSSTransitionGroup 和 React-Router v6 动画路由过渡【英文标题】:Animating route transitions with CSSTransitionGroup and React-Router v6 【发布时间】:2020-07-20 04:16:18 【问题描述】:

我开始使用 React-Router v6,并遇到了动画路由转换的问题。

react-router docs 和react-transition-group docs 都指定了与新 v6 api 不兼容的方式。

主要原因似乎是删除了<Switch> 组件。

在 react-router@v5 中,这有效:

import  Router, Route, Switch, useLocation  from 'react-router@v5'
import  TransitionGroup, CSSTransition  from 'react-transition-group'

function App() 
  const location = useLocation();

  return (
    <Router>
      <TransitionGroup>
        <CSSTransition key=location.key classNames="fade" timeout=300>
          <Switch location=location>
            <Route path="/a" children=<A /> />
            <Route path="/b" children=<B /> />
          </Switch>
        </CSSTransition>
      </TransitionGroup>
    </Router>
  );

...但是,在 react-router@v6 中,这不起作用:

function App() 
  const location = useLocation();

  return (
    <Router>
      <TransitionGroup>
        <CSSTransition key=location.key classNames="fade" timeout=300>
          <Routes location=location>
            <Route path="/a" element=<A /> />
            <Route path="/b" element=<B /> />
          </Routes>
        </CSSTransition>
      </TransitionGroup>
    </Router>
  );

似乎主要区别在于&lt;Switch&gt; 接受Location 属性的方式,并将保持两条路由渲染足够长的时间以完成转换。

没有它,似乎路线入口动画很突然。有趣的是,嵌套路由的退出动画似乎可以正常工作。

任何想法如何使用 react-router v6 获得过渡动画?

【问题讨论】:

【参考方案1】:

您似乎希望同时在屏幕上显示两个相应的组件;也就是说,新组件将在旧组件动画输出时进行动画处理。

在 v6.0.0-beta.3 之前这是不可能的。

但现在可以(在 v6.0.0-beta.3 之后)感谢将 location 属性重新添加到 &lt;Routes&gt; 组件。 (release notes for v6.0.0-beta.3)

您的示例代码只需要对 react-router@v6-beta.3 进行 2 次修改,但需要对 react-router@v6 进行第 3 次修改:

    &lt;Router&gt; 应该改为 Web 兼容路由器,例如 &lt;BrowserRouter&gt;useLocation() 挂钩必须在 路由器组件的上下文中使用。要解决这个问题,您需要先将路由器包裹在父组件中,然后才能在路由器的任何子组件中使用挂钩。 将children 属性替换为element 属性,否则会出现all component children of &lt;Routes&gt; must either be a &lt;Route&gt; or &lt;React.Fragment&gt;. 错误

另外 - 有助于了解动画路线 - "&lt;TransitionGroup&gt; renders a &lt;div&gt; by default" 有时会与动画混淆。因此,在 props 中传递 component=null 以阻止它这样做会很有帮助。

DEMO:所有这些更改都可在此codesandbox:

中找到

【讨论】:

感谢您的演示,非常棒!但是知道如何只为Outlet 内容制作动画吗?假设我有一个在所有页面上都可用的带有“固定”部分的布局。我分叉了your example and enriched with nested routes with a layout。【参考方案2】:

react-router-v6 发生了变化。阅读here和here

要使您的动画正常工作,请将 Switch 替换为 Routes(无需提供位置)。将element 属性提供给Route。同时安装history库。

我使用 v6 做了一个工作演示。进入和离开动画都在工作。将代码与您的代码进行比较。

【讨论】:

这个还是有问题的。如果您在示例中注意到,在转换时,出去的 Route 将更改为进来的新 Route。在 v5 中情况并非如此,因为您可以传入一个允许 Route 去和 Route 进来的 location 道具代表他们的正确路线,而不仅仅是活动的。有关此特定问题的活动线程,请参阅 here。【参考方案3】:

与此同时,此问题已得到修复。 这里提到了这个问题here。

在此处查看工作代码示例:here。

【讨论】:

以上是关于使用 CSSTransitionGroup 和 React-Router v6 动画路由过渡的主要内容,如果未能解决你的问题,请参考以下文章

使用水平滚动处理 React 动画

TransitionGroup 和 CssTransition:未应用退出过渡

React Transition Group:偏移动画开始时间

[react] 如何用React实现滚动动画?

如何运行使用旧版本包和最新 R 版本和包中的 R 编写的 R 脚本? [关闭]

r 尝试使用R和Javascript等