2

I need to do some animations within nested routes (using react-transition-group v5.2.0, for what that is worth).

Following the example, in the react-transition-group docs I am able to get regular routes animation going using CSSTransition, but the same cannot be said for nested routes. They simply do not animate and their expected classes from CSSTransition are not injected in the component as expected (*-enter, *-enter-active, *-exit, *-exit-active).

My current component with nesting routes looks like the following:

function Example () {
  const { params } = useRouteMatch() || {}
  const history = useHistory()

  return (
    <>

      [EXISTING_CONTENT]

      <button onClick={()=> goToTheNextRoute()}>Click me!</button>

      <Route path="/example/:nestedId">
        {({ location }) => {
          const { pathname } = location
          return (
            <CSSTransition
              in={pathname.includes(params?.nestedId)}
              timeout={500}
              classNames="nested-animation"
              mountOnEnter 
              unmountOnExit
            >
              <div className="nested-animation">
                My nested routes I'd like to animate at every click: &nbsp;
                <h3>Current Nested Route: {params?.nestedId}</h3>
              </div>
            </CSSTransition>
          )
        }}
      </Route>
    </>
  )
}

Here is also a sandbox app which is also based off the simple route example from the documentation.

What am going for is to have an animation on the div of className nested-animation every time the nested route is updated.

theJuls
  • 6,788
  • 14
  • 73
  • 160

1 Answers1

0

This is a case for the TransitionGroup component in react-transition-group. Simply import the above in the same line as CSSTransition and wrap it around the transition you want to animate.

Change the CSSTransition attributes to remove in and replace it with key. This is similar to an array map, where it needs a unique key to know what it is transitioning (it works with cloned elements). Set the value of key to params?.id since you have that already.

You can remove mountOnEnter and unmountOnExit as the transition group takes care of the mounting.

You don't need to change your style selectors, but you might have to futz with the properties to get it to behave correctly

There is a gotcha. When I mentioned it works with cloned elements, that means you will have 2 routes on screen at once while it is transitioning. This will cause a reflow on mount and unmount. I have toyed with that for a while, and the best I can come up with is to make either the in or out element have position: absolute so it is taken out of the flow, and the elements can overlap during transition. TransitionGroup creates a div, and you can give it a className. Would be easy to make it position relative so you don't lose your content while it's position absolute.

Code

import { CSSTransition, TransitionGroup } from 'react-transition-group'
...
<TransitionGroup>
  <CSSTransition
    key={params?.nestedId}
    timeout={500}
    classNames="nested-animation"
  >
    <div className="nested-animation">
      My nested routes I'd like to animate at every click: &nbsp; 
      <h3>Current Nested Route: {params?.nestedId}</h3>
    </div>
  </CSSTransition>
</TransitionGroup>
PsiKai
  • 1,803
  • 1
  • 5
  • 19