I have following App component:
<Route render={( { location } ) => (
<TransitionGroup component="div" className="content">
<CSSTransition key={location.key} classNames="slide" timeout={{
enter: 1000,
exit: 300
}} appear>
<Switch location={location}>
<Route exact path='/' component={Intro}/>
<Route path="/history" component={History}/>
<Route path="/rules" component={Rules}/>
<Route path="/faq" component={Faq}/>
<Route path="/feedback" component={Feedback}/>
<Route path="/partners" component={Partners}/>
</Switch>
</CSSTransition>
</TransitionGroup>
)}/>
And it works fine, but every animation executes immediately. For example, if I go from /rules
to /history
, I got full animation on both components, but history component require data from the server, so animation applied on empty container.
How could I pause animation in react-transition-group components? I have Redux, so I could change loading
variable anywhere in my app. Also, I don't want to preload all data in the store on app start.
I would make your component return null when it's loading and make the loading state determine the CSSTransition key like <CSSTransition key={location.key+loading?'-loading':''}
see example here: https://stackblitz.com/edit/react-anim-route-once
note that to make this work without duplication I had to make the component copy the loading prop and persist it in state, so that one of the copies of the component never displays (which would create a duplication of the component as seen here: https://stackblitz.com/edit/react-anim-route-twice)
<Route render={({ location }) => (
<TransitionGroup component="div" className="content">
<CSSTransition key={location.key+(this.state.loading?'-loading':'-loaded')} classNames="crossFade" timeout={{
enter: 3000,
exit: 3000
}} appear>
<Switch location={location} >
<Route exact path='/' component={Hello} />
<Route exact path='/history' render={() =>
<Delayed setLoading={this.handleSetLoading} loading={this.state.loading} />} />
</Switch>
</CSSTransition>
</TransitionGroup>
)} />
and in the component something like this:
export default class History extends React.Component {
state={loading:this.props.loading}
componentDidMount() {
setTimeout(() => {
this.props.setLoading(false);
}, 2000);
}
render() {
return !this.state.loading ? <div><h1>History! <Link to="/">Home</Link></h1></div> : null;
}
}
So my cases have been a bit different but they might help you think of a solution.
if (this.state.isloaded == true)
block around your whole router. Start loading when your component mounts, and when the async call completes, setState({isloaded: true})
.<Link>
component, which launches a request, and only once it’s complete changes the page location. You can do whatever special loading spinners you like in the meantime.Basically, keep the routing and transition components to one side. I find them to be brittle and painful with cases like this. Let me know if you want any more details or snippets.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With