One simple solution would be to not use a traditional link. If you add a custom event listener you can just start a timeout with startTimeout(namedFunctionToSetLocation, 200ms). I strongly recommend being frugal and using flags to control the state complexity, which will otherwise try and eat you alive.
In more detail:
- When someone triggers your event listener, firstly set some state which will add your classes "app-leave" and "app-leave-active". You can do this in a separate function but make sure to bind the function to your component's - thisso it can access- this.state, or pass the state in when rendering.
 
- In that function, you also want to start a timeout, so you can do the next you do of changes after a delay. It's worth generating an ID at this point, or setting a flag, so you can check after the delay that nothing else has begun in that time (if you use one ID variable for all transitions, and just update every time a new one begins, you should have a rock solid check whether, after an async delay, you still care about continuing). 
- When the timeout is triggered, and you've checked your flag, you can manually trigger your router, or set a new location, however you like.  
I've found it useful to use a simple bespoke approach when ReactTransitionGroup isn't a perfect fit. The transition group has nuanced behaviours with ReactRouter v4, and it's completely unnecessary if all you need is a delay or simple class change on click. 
Finally, you can also use the normal ReactRouter and ReactTransitionGroup components inside of conditional rendering blocks (like those I just described)- don't pass off that technique, it's as React-ee as it gets.