In the example sandbox below I have a parent React Router rendering two animated components.
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. If I remove the key, it breaks the animation.
Steps:
select About. note correct entry and exit animations. select Contact. 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:
The location.pathname key is forcing re-renders when selecting deep nested links. what can i sensibly replace it with so that it doesn't re-render? Ive tried removing it, but that breaks the animation.
thanks
solved: i have replaced the location.pathname with a component specific state key on the router wrappers with useState.
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. Because the key will still be the same: 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.
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>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.