简体   繁体   English

Framer Motion 和 React 路由器 5:如何防止使用嵌套路由重新渲染父组件?

[英]Framer Motion and React router 5: How do I prevent re-render of parent components with nested routes?

In the example sandbox below I have a parent React Router rendering two animated components.在下面的示例沙箱中,我有一个父 React Router 渲染两个动画组件。

https://codesandbox.io/s/frame-motion-x-react-router-x-simple-tb1wg?file=/src/Routes.tsx https://codesandbox.io/s/frame-motion-x-react-router-x-simple-tb1wg?file=/src/Routes.tsx

One of them contains its own nested links - each with their own independent framer-motion animations.其中一个包含自己的嵌套链接——每个链接都有自己独立的成帧运动动画。 I need to stop the parent of the nested switch re-rendering when i click a route link.当我单击路由链接时,我需要停止嵌套开关的父级重新渲染。 I can see the problem is related to use of the switch key on both levels but i dont know what to replace it with to stop re-rendering higher up the component hierarchy.我可以看到问题与在两个级别上使用 switch 键有关,但我不知道用什么替换它以停止重新渲染组件层次结构的更高层。 If I remove the key, it breaks the animation.如果我删除密钥,它会破坏 animation。

Steps:脚步:

select About. select 关于。 note correct entry and exit animations.注意正确的进入和退出动画。 select Contact. select 联系方式。 note the correct entry and exit animations.注意正确的进入和退出动画。 select Child 1. note the unwanted re-render of the parent component select Child 2. note the unwanted re-render of the parent component Notes: select Child 1. 注意父组件不需要的重新渲染 select Child 2. 注意父组件不需要的重新渲染 注意:

  • i've added some Math.random() calls inline which change on re-render我添加了一些内联的 Math.random() 调用,这些调用在重新渲染时会发生变化
  • i've included a top level link with no animation to demonstrate the nested components animate on mounting as expected.我已经包含了一个没有 animation 的顶级链接,以演示嵌套组件在安装时按预期设置动画。 however it is still re-rendering on selection of child links.但是,它仍然会在选择子链接时重新呈现。

The location.pathname key is forcing re-renders when selecting deep nested links. location.pathname 键在选择深层嵌套链接时强制重新渲染。 what can i sensibly replace it with so that it doesn't re-render?我可以用什么明智地替换它,以免它重新渲染? Ive tried removing it, but that breaks the animation.我试过删除它,但这会破坏 animation。

thanks谢谢

solved: i have replaced the location.pathname with a component specific state key on the router wrappers with useState.已解决:我已将 location.pathname 替换为带有 useState 的路由器包装器上的组件特定 state 密钥。

https://codesandbox.io/s/framer-motion-nested-routes-react-router-747yw https://codesandbox.io/s/framer-motion-nested-routes-react-router-747yw

result: the child route animations work indepedently of the parent routes and vice versa.结果:子路由动画独立于父路由工作,反之亦然。 could be improved by preventing multiple repeat re-routes on single links.可以通过防止单个链路上的多次重复重新路由来改进。 suggestions welcome.欢迎提出建议。

a simpler solution would be to use the root pathname as the key.一个更简单的解决方案是使用根路径名作为键。

So that AnimatePresence won't re-animate the switch when it changes from /topics to /topics/react for example.例如,当 AnimatePresence 从/topics更改为/topics/react时,它不会重新设置开关的动画。 Because the key will still be the same: topics .因为关键仍然是相同的: topics

<AnimatePresence>
  <Switch location={location} key={location.pathname.split('/')[1]}>
    <Route path="/" exact>
      <Home />
    </Route>
    <Route path="/topics">
      <Topics />
    </Route>
  </Switch>
</AnimatePresence>

You can of course go further, and extract that to a function that will give you the appropriate key per-nested-level.您当然可以进一步 go 并将其提取到 function ,这将为您提供适当的每个嵌套级别的密钥。

const getPathKey = (path, level = 1) => {
  // path: "/topics/react/router"
  // level: 1 -> topics
  // level: 2 -> topics/react
  // level: 3 -> topics/react/router
  return path.split('/').splice(1, level).join('/');
}
<AnimatePresence>
  <Switch location={location} key={getPathKey(location.pathname)}>
    ...
      
      <AnimatePresence>
        <Switch location={location} key={getPathKey(location.pathname, 2)}>
           ...
        </Switch>
      </AnimatePresence>

  </Switch>
</AnimatePresence>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM