4

I'm using react-router and I want to be able to render and transition arbitrary components when mounting and unmounting. Right now I have added the components to my route definition:

<Route component={App}> <Route path="foo" component={Foo} /> <Route path="bar" component={Bar} /> </Route> 

I use react css transition group in my components to animate them when they enter and leave. The components mount and animate propery when they are entering. But when I leave the route, the rendered component is immediately removed and there is thus no leave animation.

The typical solution is to add the transition group to the parent so that it isnt unmounted, and from there animate the children. This doesn't work for me because Foo component and Bar component use completely different animations.

In short I believe I need a way to individually animate routes and not the typical "transition between routes". For example, navigating between / and /foo should yield the following:

  1. Be on /, navigate to /foo -> the Foo component animates in.
  2. Be on /foo, navigate to anywhere else, like / -> the Foo component animates out.

I hope this makes sense, thanks!

1
  • I have added some example. Commented Jul 12, 2016 at 16:08

1 Answer 1

4

Maybe, you can delay transition, in order to allow to complete "leave" animation

1) with onChange jsfiddle example: https://jsfiddle.net/qnpj0odc/7/

const func = ({location:{pathname:prev}}, nextState, replace, callback)=>{ prev=="/foo" ? setTimeout(callback,3000) :prev=="/bar" ? setTimeout(callback,2000) :callback(); }; <Route path="/" component={App} onChange={func}> <Route path="foo" component={Foo} /> <Route path="bar" component={Bar} /> </Route> 

enter image description here


2) with setRouteLeaveHook https://jsfiddle.net/qnpj0odc/24/

class Foo extends React.Component{ constructor(props){ super(props); this.state={leave:0}; props.router.setRouteLeaveHook(props.route,n=>this.startAnim(n)) } startAnim(next){ this.setState({leave:1}); setTimeout(()=>{ this.allow=1; this.props.router.push(next.pathname);},500) return !!this.allow; } render(){ return ( <h1 className={"animated zoomIn"+(this.state.leave?" zoomOut ":"")}>FOO</h1> ); } } 

3) with listenBefore https://jsfiddle.net/qnpj0odc/23/

class Foo extends React.Component{ constructor(props){ super(props); this.state={leave:0}; this.cb = props.router.listenBefore((loc,cb)=>{ loc.pathname == props.location.pathname ? this.setState({leave:0}) : this.setState({leave:1},()=>setTimeout(cb,500))}); } componentWillUnmount(){ this.cb(); //unlisten } render(){ return ( <h1 className={"animated zoomIn"+(this.state.leave?" zoomOut ":"")}>FOO</h1> ); } } 
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the swift reply. This seems like an alright solution, but means I have to stick extra animation login into my routing table which does not seem ideal and might quickly get out of hand. Double maintenance problems etc.
I have added example without onChange in routing table

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.