How could you pause animation in react-transition-group while loading initial data in components?

react-transition group hooks
react-transition group demo
react-transition-group keyframes
react-transition-group typescript
react animation on state change
react css transition not working
react fade in fade out
react page transitions

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;
  }
}

Animating Between Views in React, First, let's get familiar with the react-transition-group library to examine how we For example, the Switch component in react-router-dom expects direct Route const timeline = new Timeline({ paused: true }); const texts = node. This caused a visual lag on the animation for the first load of the application. ReactTransitionGroup and ReactCSSTransitionGroup have been moved to the react-transition-group package that is maintained by the community. Its 1.x branch is completely API-compatible with the existing addons. Please file bugs and feature requests in the new repository. The ReactTransitionGroup add-on component is a low-level API for animation, and ReactCSSTransitionGroup is an add-on component for easily implementing basic CSS animations and transitions.

So my cases have been a bit different but they might help you think of a solution.

  1. You can delay the initial display easily by adding an 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}).
  2. You can make your own <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.

Animation Add-Ons – React, The ReactTransitionGroup add-on component is a low-level API for animation, and During the initial mount ReactCSSTransitionGroup will get the However, the default values of transitionEnter and transitionLeave are true so you must  dracontis.com. Member for 9 years 8 How could you pause animation in react-transition-group while loading initial data in components? Nov 26 '18.

I've done peloading through redux and redux-saga. Maybe it's one and only way to achieve following with react-router and react-transition-group, because transition toggle animation anytime when render method is run, even if it return null.

I've implemented following actions:

const LoadingActions = {
    START_LOADING: 'START_LOADING',
    STOP_LOADING: 'STOP_LOADING',
    REDIRECT: 'REDIRECT',

    startLoading: () => ({
        type: LoadingActions.START_LOADING
    }),

    stopLoading: () => ({
        type: LoadingActions.STOP_LOADING
    }),

    redirect: ( url, token ) => ({
        type: LoadingActions.REDIRECT,
        payload: {
            url,
            token
        }
    })
};

export default LoadingActions;

In the reducers I've implemented simple loader reducer, that will toggle on and off loading variable:

import { LoadingActions } from "../actions";

const INITIAL_STATE = {
    loading: false
};

export default function ( state = INITIAL_STATE, { type } ) {
    switch ( type ) {
        case LoadingActions.START_LOADING:
            return { loading: true };
        case LoadingActions.STOP_LOADING:
            return { loading: false };
        default:
            return state;
    }
}

The most irritating thing is reducer chain - this.props.loader.loading. Too complex for such simple thing.

import { combineReducers } from "redux";
...
import LoadingReducer from './LoadingReducer';

export default combineReducers( {
    ...
    loader: LoadingReducer
} );

This most work goes in saga:

function* redirect ( action ) {
    yield put( LoadingActions.startLoading() );
    const { url } = action.payload;

    switch ( url ) {
        case MENU_URL.EXCHANGE:
            yield call( getExchangeData, action );
            break;
        ... other urls...
    }
    yield put( LoadingActions.stopLoading() );
    BrowserHistory.push( url );
}

... loaders ...


function* watchRedirect () {
    yield takeLatest( LoadingActions.REDIRECT, redirect );
}

const sagas = all( [
    ...
    fork( watchRedirect )
] );

export default sagas;

I put listener on redirect action, so it will call redirect generator. It will start loading and call data preloading yield call will await for preload to finish and after it will stop loading and redirect. Though it won't wait for positive result, so preloaders should handle errors themselves.

I hoped that I could avoid redux complexity with built-in feature of router or transition library, but it has no such tools to stop transition. So it is one of the best way to achieve transition with preloded data.

Animate React Component Loading, CSS Transitions can make your app / website look professional. the AnimateLoad wraps a component and returns it, after manipulating the  react-loading. Easy to use loading animations for React projects. Uses SVG animations from Brent Jackson's loading project.

Transition component, Most commonly it's used to animate the mounting and unmounting of a component, but If you're using transitions in CSS, you'll probably want to use CSSTransition instead. For example we can add styles to a component when it enters or exits: If you want to "lazy mount" the component on the first in={true} you can set  For more flexible animation choices, we are using react-lottie. You can search for your favorite animation to use at LottieFiles. Let’s replace our current react loader with a lottie file animation.

UI Animations with React, Here is an example of my initial strategy for implementing a fade with React. the fade before you update the data which would in turn unmount the component. Then we simply need to rely on the power of CSS transitions. package, react-​transition-group, which is now supported by the community and  Depending on the element that is entering, the exiting animation changes, and vice versa. For example, in the image above, when the blue enters, red moves right, and when the blue exits, red moves left. However when the green enters, red moves left and when the green exits, red moves right.

Enhance App User Experience with React Animations & Transitions, By simply adding a fade in animation on your page load, and following a The transition CSS property accepts the following values. the velocity of the transition at the end, instead of coming to a sudden stop. ReactTransitionGroup exposes transition stages, manages classes and group elements and  However, the children of CSSTransitionGroup can also be one or zero items. This makes it possible to animate a single element entering or leaving. Similarly, you can animate a new element replacing the current element. For example, we can implement a simple image carousel like this: import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup' ; function ImageCarousel ( props) { return ( < div > < CSSTransitionGroup transitionName ="carousel" transitionEnterTimeout = { 300 }

Comments
  • When are fetching data for the new container, is it on componentWillMount ?
  • @RohitGarg yes, I've tried this. But this won't solve this issue, because fetching data is Promise (axios if this matters), so render() will be fired before finishing data load so it will trigger animation from react-transition-group and after some time data appear on the screen.
  • Can't figure out how this could help me. Should I wrap each route with CSSTransition or have it inside each component? I've tried to return null in render for components, but it just renders animation for enter/exit on previous component and null. So when data is ready it just renders page.
  • It does work, because setting the CSSTransition key makes it assume another transition when the load is done, but it has a small flaw which makes the loaded route appear twice. I'm editing to include links to working code (with this flaw and also with that fixed)
  • this loading behavior can then be extracted to a HOC to keep the real component and the routes clean
  • I'm sorry, but small flaw is unacceptable in real applications, because there is no point in animation with such strange behaviour.
  • Also, after it rendered it works a bit strange. If you press Home > History first time it will work flawlessly, but when you press History > Home it renders two components the same time. We've solved such issue in our project, but it still could be a small enhancement for this example.
  • First approach is not an option, because it will remove current page so it won't be visible during loading process. Second option is better, but instead of Link component I could create custom redirect methods in Redux, and I want something different.
  • Re 1, You could have the other page respond to a second flag in the first option. It's basically building your own state manager, which can be hell, but the CSS Transitions framework is very picky with React Router, so I think it's a good skill to have. The link option seems much easier tbh, and if you do make it a component you can nicely encapsulate it's state and data payload, and pass its existence up and down with props and state. But, I'm from iOS land, I have weird ideas about how to do things.