React-transition-group: Exclude some Routes from transition.

Created on 3 Jul 2018  路  7Comments  路  Source: reactjs/react-transition-group

I have to exclude one Route from transition group. Given below the code

<Route
  render={({ location }) => (
    <div className="App">
      <TransitionGroup className="transition-item">
        <CSSTransition
          key={location.key}
          timeout={300}
          classNames="fade"
        >
          <Switch location={location}>
            <Route
              path="/login"
              exact
              render={routeProps => (<LoginPage {...routeProps} />)}
            />
            <Route
              path="/logout"
              exact
              render={(routeProps: any) => (<LogoutPage {...routeProps} />)}
            />
            <PrivateRoute
              path="/"
              exact
              render={(routeProps: any) => <HomePage />}
            />
            <PrivateRoute
              path="/profile"
              exact
              render={(routeProps: any) => (<Profile {...routeProps} />)}
            />
          </Switch>
        </CSSTransition>
      </TransitionGroup>
    </div>
  )}
/>

Transition works fine for this code. But I want to remove transition animation of /profile Route.
Is there any way to remove it?
Is there any way to maintain profile route inside switch and solve this issue?

Most helpful comment

when children is a function for Route, it gets called regardless of whether the route is matched or not: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Route.js#L122

Could do something like

<Route>
  {({ match }) => <Transition in={!!match} />
</Route>

All 7 comments

hacky, but works: <CSSTransition key={location.key} timeout={somecond ? 500 : 0} classNames={somecond ? 'working-class' : ''}>.... better idea?

@ondrejrohon I could not find any perfect condition there. I added location.pathname !== '/profile' as condition. But will fail when we navigate to profile. Navigation from profile works well.

I think this requires some rendering acrobatics because we can enable/disable exiting transition only _before_ we know what the next route will be. One solution is this:

<Route
  render={({ location }) => {
    const routes = (
      <Switch location={location}>
        <Route
          path="/login"
          exact
          render={routeProps => (<LoginPage {...routeProps} />)}
        />
        <Route
          path="/logout"
          exact
          render={(routeProps: any) => (<LogoutPage {...routeProps} />)}
        />
        <PrivateRoute
          path="/"
          exact
          render={(routeProps: any) => <HomePage />}
        />
        <PrivateRoute
          path="/profile"
          exact
          render={(routeProps: any) => (<Profile {...routeProps} />)}
        />
      </Switch>
    )

    return (
      <div className="App">
        {[
          { name: 'Login', pathname: '/login' },
          { name: 'Logout', pathname: '/logout' },
          { name: 'Home', pathname: '/' },
          { name: 'Profile', pathname: '/profile' },
        ].map(({ name, pathname }) => (
          <Link
            key={pathname}
            to={{ pathname, state: { fromPathname: location.pathname } }}
          >
            {name}
          </Link>
        ))}
        {location.pathname === '/profile' ? routes : (
          <TransitionGroup
            enter={location.state.fromPathname !== '/profile'}
            className="transition-item"
          >
            <CSSTransition
              key={location.key}
              timeout={300}
              classNames="fade"
            >
              {routes}
            </CSSTransition>
          </TransitionGroup>
        )}
      </div>
    )
  }}
/>

It consists of three parts:

  1. Saving the previous route using location state in Link components.
  2. Rendering only routes if current route is /profile. This will prevent exiting animation of any previous route and entering animation of the current (profile) route.
  3. Disabling enter animation on TransitionGroup if the previous route was /profile. When navigating away from /profile, this will prevent the entering animation of the new route.

I'm not sure what are your exact animation requirements, so you can tweak these as you wish. Let me know if you have questions!

I honestly having played around with React router in a while but it seems like to do transitions, Route should be the thing with the Transition in it and there should be no TransitionGroup...

How would you make an exit transition in that case?

when children is a function for Route, it gets called regardless of whether the route is matched or not: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Route.js#L122

Could do something like

<Route>
  {({ match }) => <Transition in={!!match} />
</Route>

Oh wow, that was my missing piece of the puzzle!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Medsestrun picture Medsestrun  路  5Comments

nickmccurdy picture nickmccurdy  路  4Comments

mosesoak picture mosesoak  路  5Comments

Alfrex92 picture Alfrex92  路  4Comments

vedimension picture vedimension  路  5Comments