Hi, how to use it with react router 4?
transitionAppear={true}
transitionAppearTimeout={500}
transitionEnter={true}
transitionEnterTimeout={500}
transitionLeave={true}
transitionLeaveTimeout={500}>
{ React.cloneElement(this.props.children, { key: this.props.location.pathname })}
Doesn't work
i don't know! That's more of a question for react-router
@atwaves There is a section on animated transitions in the React Router docs. It uses ReactCSSTransitionGroup, so it should help you get started.
https://reacttraining.com/react-router/web/example/animated-transitions
Hi,
Route.children-func is also a good helper in this case
https://reacttraining.com/react-router/web/api/Route/children-func
<Route exact path="/" children={({ match, ...rest }) => {
return (<TransitionGroup>
{ match && <TodoList {...rest}/>}
</TransitionGroup>)
}}/>
and
class TodoList extends React.Component {
componentWillAppear(cb) {
console.log('TodoList componentWillAppear')
setTimeout(cb, 500)
}
componentDidAppear() {
console.log('TodoList componentDidAppear')
}
componentWillEnter(cb) {
console.log('TodoList componentWillEnter')
setTimeout(cb, 500)
}
componentDidEnter() {
console.log('TodoList componentDidEnter')
}
componentWillLeave(cb) {
console.log('TodoList componentWillLeave')
cb()
}
componentDidLeave() {
console.log('TodoList componentDidLeave')
}
render() {
return (<div>lorem ipsum</div>)
}
}
The problem with the example in the react-router docs is that they (conveniently) render a single route inside the TransitionGroup (CSSTransitionGroup in the example). The route renders the same component with different props and key, so you get the transition.
But as soon as you have 2 distinct routes, the TransitionGroup handles both of them as if they were visible, when in reality only 1 route will end up rendering something (at least in most cases). So now you have 2 visible children inside the TransitionGroup when we only want 1.
The problem with @jeromedecoster's example is that the TransitionGroup is rendered inside the route, so if you have 2 routes, you would actually have 2 different TransitionGroup components.
I think the solution is boiling down to somehow only render the matched Route components inside the TransitionGroup, but this is kind of what the Router does (basically a non matched Route renders null effectivley not showing your configured component).
Any ideas?
With reference to https://github.com/maisano/react-router-transition, I managed to get it working with the below:
<Router>
...
<nav>
<NavLink to="/" exact activeClassName="active"> <span>Production</span> </NavLink>
<NavLink to="/personal" activeClassName="active"> <span>Personal</span> </NavLink>
</nav>
...
<Route render={({ location }) => (
<CSSTransitionGroup
transitionName="slide-left"
transitionEnterTimeout={300}
transitionLeaveTimeout={500}
>
<Switch key={location.key} location={location}>
<Route exact path="/" component={Production}/>
<Route path="/personal" component={Personal}/>
</Switch>
</CSSTransitionGroup>
)}
/>
</Router>
Great demo @resting thank you a lot !
I'm currently working on feature which implements left-to-right and right-to-left animation for routes depending on current router "position" to fire specific animation. If anyone else interested in this one case let me know so I'll update you when it'll be ready.
@eko24ive i'd be curious on your solution; can you also provide one with using the low-level TransitionGroup as well?
@sunnyvempati sure, I'll prepare my code and push it to repo and share link here
@sunnyvempati hey, take a look https://github.com/eko24ive/react-router-transitions
@eko24ive following the above example code (or following react router's official documentation animation example code) didn't work out for me. Routing works, but just without any animation at all.
FYI, here's my code snippet:
application.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, combineReducers, compose } from 'redux';
import { persistStore, autoRehydrate } from 'redux-persist';
import { Provider } from 'react-redux';
import * as reducers from '../reducers';
import App from '../App';
const store = createStore(
combineReducers(reducers),
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
compose(autoRehydrate())
);
persistStore(store);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
App.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import { CSSTransitionGroup } from 'react-transition-group';
import Snackbar from './components/Snackbar';
import LoginScreen from './components/LoginScreen';
import SignupScreen from './components/SignupScreen';
import AuthenticatedScreenContainer from './components/AuthenticatedScreenContainer';
class App extends Component {
componentDidUpdate(prevProps) {
const { history, redirectUrl } = this.props;
const isLoggingOut = prevProps.isLoggedIn && !this.props.isLoggedIn;
const isLoggingIn = !prevProps.isLoggedIn && this.props.isLoggedIn;
if (isLoggingIn) {
history.replace(redirectUrl || '/');
} else if (isLoggingOut) {
history.replace('/login');
}
}
render() {
return (
<Router>
<Route render={({ location }) => (
<div className="container d-flex align-items-center justify-content-center" style={{ height: '100vh' }}>
<div className="w-100">
<CSSTransitionGroup
transitionName="fade"
transitionEnterTimeout={300}
transitionLeaveTimeout={500}
>
<Switch key={location.key} location={location}>
<Route path="/login" component={LoginScreen} />
<Route path="/signup" component={SignupScreen} />
<Route component={AuthenticatedScreenContainer} />
</Switch>
</CSSTransitionGroup>
<Snackbar />
</div>
</div>
)} />
</Router>
);
}
}
const mapStateToProps = (state) => ({
isLoggedIn: !!state.auth.access_token,
redirectUrl: state.redirectUrl
});
export default connect(mapStateToProps)(App);
Here is a working fade page transition example with React Router v4 and React Transition Group v2: https://codesandbox.io/s/4RAqrkRkn?view=preview
Related issue on how it was created.
I think the problem occurs because of HashRouter.
@clthck Sorry for such long reply.
Does animation from my repo worked fine for you ?
I'm not sure if HashRouter affects transition animations but you should try other Router type just for sure.
@clthck You also might be interested in pull request by @nbgraham in my repo https://github.com/eko24ive/react-router-transitions/pull/1 regarding HashRouter. It seems that he was able to implement support for it - check it out !
@VladShcherbin - thank you, your example saved me from 2 days of head scratching... very straightforward in the end....
BTW, if anyone woulds like to contribute some docs on using RTG v2 with react-router, i'd be very appreciative :)
@jquense sure, I could spare some time into it
@eko24ive have you been able to work on those docs? I'd really appreciate some direction on how to use RTG v2 with react-router.
Thanks!
@bernatfortet sorry to give you bad news - currently, I can't spend time on this due to reasons. But I definitely going to contribute to this issue ASAP.
I wrote an article dealing with react-router v4 & react-transition-group: https://medium.com/lalilo/dynamic-transitions-with-react-router-and-react-transition-group-69ab795815c9. There is a repo with demo available. Hope it can help
Most helpful comment
Here is a working fade page transition example with React Router v4 and React Transition Group v2: https://codesandbox.io/s/4RAqrkRkn?view=preview
Related issue on how it was created.