React Router and framer motion Animate Presence

Viewed 5613

When I added 'exitBeforeEnter' prop to the Animate Presence component with nested routes, the routes didn't render at all but when I refreshed the page they rendered, removing this prop or go to the component directly will fix it, but I need to use the prop and the redirect component from react-router

This is my code:

<AnimatePresence exitBeforeEnter>
                <Switch location={this.props.location} key={this.props.location.pathname} >
                    <Route exact path='/home' component={() => <.../>

                    <Route path='/home/:alpha3Code' component={({match}) =>
                        .... />

                    <Redirect to='/home' />
                </Switch>
</AnimatePresence>
4 Answers

from exitBeforeEnter docs

If set to true, AnimatePresence will only render one component at a time. The exiting component will finished its exit animation before the entering component is rendered.

You have to specify exit animations for all components that you are using inside AnimatePresence. On route changes, AnimatePresence will execute exit animations first and then only it will render next component. If a component does not have exit animation and it is child of AnimatePresence, then route change will only change the url not the view.

That's normal if you will not add an exit animation to each and every routes.

Main route with AnimatePresense

<AnimatePresence exitBeforeEnter>
  <Switch location={window.location} key={window.location.pathname}>
    <Route exact path='/' component={Home} />
    <Route exact path='/about' component={About} />
    <Route path="*">Page not found</Route>
  </Switch>
</AnimatePresence

About.jsx

const exit = {
  exit: {
   opacity: 0,
  },
}
export default function About() {
  return <motion.h1 {...exit}>Hello</h1>
}

Home.jsx

const exit = {
  exit: {
   opacity: 0,
  },
}
export default function Home() {
  return <motion.h1 {...exit}>Hello</h1>
}

For those of you still lost, you need to wrap the <motion.div> tag AROUND the < redirect > tag with an "exit" parameter as mentioned in the other answers. Example code is provided below.


return (
            <motion.div exit='exit' variants={PageTransition} initial='hidden' animate='show' className='login-container'>
                <Redirect to='/Dashboard' />
            </motion.div>
        );

Does anyone have an update with react-router-dom v6 ?

I'm rewriting a small app I made some months ago, and it was working perfectly before, with AnimatePresence and Switch Router components. Exit transitions were running successfully between pages changes.

Now for some reason, exit transitions don't trigger on page change, and I suspect it may be because of the changes made to react-router-dom API and components use.

In react-router-dom v6, it looks more like that :

const App = function () {
  return (
    <AnimatePresence exitBeforeEnter>
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<Layout />}>
            <Route
              path="characters"
              element={<Characters />}
            />
          </Route>
          <Route path="login" element={<Login />} />
        </Routes>
      </BrowserRouter>
    </AnimatePresence>
  );
};

And the Layout component :

<motion.div
  key="layout"
  initial={{ opacity: 0 }}
  animate={{ opacity: 1 }}
  exit={{ opacity: 0 }}
  transition={{ duration: 0.7 }}
>
  <Menu />
  <div>
    <Outlet />
  </div>
</motion.div>

Exit transition doesn't trigger, unfortunately.

Related