0

I'm using React router for a project. I would like to animate a single route, which lives inside a parent route (basically, a single project will appear as a "modal" on top of the list of projects, so the content of the parent route need to persist when the child route is visible.

The routing works fine now, but the struggle comes when animating. I remember seeing an example at some point where a sidenav was being animated in as a route, but I can't find it anywhere now...

Example code: https://codesandbox.io/s/1447zpvlzj

Current behavior: I'm following the example on the react router tutorial When adding the key to the like in the example, the application breaks on route change. When the key is removed, the route changes, but the transition doesn't happen (enter and exit classes are not added to the route).

I also tried wrapping the route in a div instead of the Switch. This actually gave me a proper transition on enter. However, the on exit transition would break because the route content (the content inside the wrapper div) would actually disappear before the exit transition timeout was finished

Marcos Mellado
  • 125
  • 2
  • 11

1 Answers1

0

Solution ended up being a bit tricky

In the end, I had to create a new component (Drawer) to handle the animation. Then, added the child route to the <Switch> and pointed it to the parent component like this:

App.jsx

<Switch>
    <Route exact path="/" component={Home} />
    <Route path="/projects/:slug" component={Projects} />
    <Route path="/projects" component={Projects} />
    <Route component={NotFound} />
</Switch>

This means that no matter if I hit /projects or /projects/foo, the same Projects component will load.

Then, in my Projects component I render the individual Project component conditionally, based on the presence of my slug. I do this inside the Drawer component I created which handles the animation (with this approach, react-transition-group was not needed anymore, I animate via CSS based on the Drawer being open or not)

Projects.jsx

render() {
  const renderProject = !!this.props.match.slug;

  return (
    <div className="projects">
      [projects content here]
      <Drawer isOpen={renderProject}>
        <Project />
      </Drawer>
    <div>
  )
};

This allows the slugged route to live within the parent route, while still being animated by the Drawer component when the slug becomes present.

Finally, I used the withRouter HOC provided by react-router-dom to wrap the exported <Project> component, so that it can leverage the Router entirely.

Project.jsx

export default withRouter(Project);
Marcos Mellado
  • 125
  • 2
  • 11