Skip to content

[v6] First-class animation primitives #7946

@mjackson

Description

@mjackson

What is the new or updated feature that you are suggesting?

React Router v6 should include first-class primitives for supporting animations on route transitions.

A bit of history here: in v4/5, we added the <Switch location> prop. This prop provided a way for you to keep the <Switch> rendering an old location when it is rendered inside another element with a key that is used to perform an animation, such as a <CSSTransition> from react-transition-group. It looked something like this:

function App() {
  let location = useLocation();
  return (
    <TransitionGroup>
      <CSSTransition key={location.key}>
        <Switch location={location}>
          {/* routes go here */}
        </Switch>
      </CSSTransition>
    </TransitionGroup>
  );
}

This API worked fine for v4 and v5, but it's not entirely clear outside of the context of animations that the <Switch location> prop is to be used for animations. It was proposed in #7117 that we add a <Routes location> prop that could be used in v6. However, since v6 is built entirely on React hooks, I think we can do better.

Instead of a location prop, we can provide "animated" versions of all components and hooks that give you elements to render. So, for example, the animated version of <Routes> would be <AnimatedRoutes>. You could use it exactly like <Switch location>, except it's much more clear what it's for.

function App() {
  let location = useLocation();
  return (
    <TransitionGroup>
      <CSSTransition key={location.key}>
        <AnimatedRoutes>
          {/* routes go here */}
        </AnimatedRoutes>
      </CSSTransition>
    </TransitionGroup>
  );
}

In addition to <AnimatedRoutes> we can also provide:

  • <AnimatedOutlet>
  • useAnimatedRoutes()
  • useAnimatedOutlet()

Each of these elements and hooks would ofc work exactly like the non-animated version but with one important difference: they don't subscribe to location updates from context. Instead, they must be used inside another element with a key that will be unmounted in the transition.

AFAICT all animation libraries for React work this way. They rely on a key changing on an element to know when an element is going to transition out/in.

Why should this feature be included?

Providing animation primitives should make it easier for people to do animations between routes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions