React Router v4 and React Transition Group v2

1.9k views Asked by At

I am trying to find a working example of low level animations using the React Router v4 with React Transition Group v2. I have looked at the example on the React Router docs but they only use CSS Animation with one route.

This is how I currently use the React Router:

export const App = () => (
  <div className="app-container">
    <main className="app-container__content">
      <Switch>
        <Route exact path="/projects/:slug" component={ProjectPage} />
        <Route exact path="/" component={StartPage} />
      </Switch>
    </main>
  </div>
);

And this is my Root.jsx:

const Root = ({ store, history }) => (
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <Switch>
        <Route path="/" component={App} />
      </Switch>
    </ConnectedRouter>
  </Provider>
);

I have tested the solution here: https://hackernoon.com/animated-page-transitions-with-react-router-4-reacttransitiongroup-and-animated-1ca17bd97a1a - but it doesn't work. Could some one point me in the right direction?

Update

I have tried like this, but the callback doesn't get called. So I end up with to pages in the dom.

export const App = ({ location }) => {
  console.log(location);

  return (
    <div className="app-container">
      <main className="app-container__content">
        <ScrollToTop />
        <TransitionGroup>
          <Switch key={location.pathname} location={location}>
            <Route exact path="/projects/:slug" component={ProjectPage} />
            <Route exact path="/" component={StartPage} />
          </Switch>
        </TransitionGroup>
      </main>
    </div>
  );
};
2

There are 2 answers

2
Maor Yosef On

you are missing the Transition component itself

it should look something like this:

<TransitionGroup>
  <CSSTransition
    key={location.key}
    classNames="page-animation"
    timeout={{ enter: PAGE_ENTER_ANIMATION_SPEED, exit: PAGE_EXIT_ANIMATION_SPEED }}>
    <Switch location={location}>
      <Route exact path="/projects/:slug" component={ProjectPage} />
      <Route exact path="/" component={StartPage} />
    </Switch>
  </CSSTransition>
</TransitionGroup>

notice that the key is on the CSSTransition itself and not on the Switch


Update

If you want to implement it by yourself here is a basic implementation of CSSTransition

class MyTransition extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            inTransition: true,
            playAnimation: false,
        };
    }

    componentDidMount() {
        setTimeout(() => {
            this.setState({playAnimation: true});
        }, 1);

        this.removeClassesAndFireOnExited();
    }

    removeClassesAndFireOnExited() {
        setTimeout(() => {
            this.setState({playAnimation: false, inTransition: false}, () => {
                if (!this.props.in) {
                    this.props.onExited(this);
                }
            });
        }, this.props.timeout[this.props.in ? 'enter' : 'exit']);
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.in !== this.props.in) {
            this.setState({inTransition: true});
            setTimeout(() => {
                this.setState({playAnimation: true});
            }, 1);

            this.removeClassesAndFireOnExited();
        }
    }

    render() {
        const baseClassName = this.props.in ? 'page-animation-enter' : 'page-animation-exit';
        const {inTransition, playAnimation} = this.state;

        const transitionClasses = [...(inTransition ? [baseClassName] : []), ...(playAnimation ? [baseClassName + '-active'] : [])];

        return (
            <div className={transitionClasses.join(' ')}>
                {this.props.children}
            </div>
        );
    }
}

you get this.props.in from TransitionGroup to indicate whether you are entering or leaving.
this.props.onExited is another prop that you get from TransitionGroup, you must call it when the exit animation completes, so TransitionGroup will know that you should be unmounted.

0
Nicolas Girault On

Here is an article explaining how to setup react-router v4 and react-transition-group with multiple routes and with transitions depending of the next state: https://medium.com/lalilo/dynamic-transitions-with-react-router-and-react-transition-group-69ab795815c9