为什么我需要向 Switch 组件提供位置对象才能使退出动画起作用?

Why I need to provide the location object to Switch component to make exit animation work?

我在我的应用程序中使用 framer-motion 和 react-router-dom。 我想为一些路线转换制作动画,但我失败了。尽管我使用的是来自 framer 的 AnimatePresence 组件,但路由组件被直接卸载并且没有执行退出动画。在查看了一些教程后,我注意到许多示例都在向 Switch 组件提供位置对象。我试过了,确实有效,正在执行退出动画。例如,在这段代码中:

const location = useLocation()
// ...
<AnimatePresence exitBeforeEnter>
        <Switch location={location} key={location.pathname}>
          <Route path="/names/boy">
            <motion.div
              variants={tabAnimations}
              initial="boy"
              animate="present"
              exit="boy"
            >
              <GenderList gender="M" />
            </motion.div>
          </Route>
          <Route path="/names/girl">
            <motion.div
              variants={tabAnimations}
              initial="girl"
              animate="present"
              exit="girl"
            >
              <GenderList gender="F" />
            </motion.div>
          </Route>
        </Switch>
</AnimatePresence>

如果我将 Switch 部分更改为此 <Switch key={location.pathname}> 它将停止正确跟踪子节点并且不会执行退出动画。为什么是这样? 我检查了 react-router-dom docs,但没有找到任何可以解释这一点的内容。它只说位置组件指的是使用什么位置对象,它回退到使用浏览器,仅此而已。

检查 react-router transition tutorial 动画过渡。

他们的演示中有一条评论解释了原因:

<TransitionGroup>
  {/*
    This is no different than other usage of
    <CSSTransition>, just make sure to pass
    `location` to `Switch` so it can match
    the old location as it animates out.
  */}
  <CSSTransition
    key={location.key}
    classNames="fade"
    timeout={300}
  >
    <Switch location={location}>
      <Route path="/hsl/:h/:s/:l" children={<HSL />} />
      <Route path="/rgb/:r/:g/:b" children={<RGB />} />
    </Switch>
  </CSSTransition>
</TransitionGroup>

您需要传递 整个 location 对象,以便它可以在转换期间区分位置。

参见location

Locations represent where the app is now, where you want it to go, or even where it was. It looks like this:

{
  key: 'ac3df4', // not with HashHistory!
  pathname: '/somewhere',
  search: '?some=search-string',
  hash: '#howdy',
  state: {
    [userDefined]: true
  }
}