ページ間移動時のアニメーションを実装

react-transition-group_app.jsxの中で使います。_appファイルで定義したコンポーネントはクライアント側で唯一マウントし続けるコンポーネントで、このコンポーネントが受け取るプロパティのComponentに対象のpages/*.jsxファイルのコンポーネントが入る形で来ます。

以下にフェードイン・アウトを想定した例です。( TypeScript ) router.routeCSSTransitionkeyとして使っています。これはページ移動した時にrouter.routeが切り替わり、古いkeyのものはexitに向かい、新しいkeyのページコンポーネントはenterに向かうような形になります。Componentは1つしかないはずですが、TransitionGroupを使うことでアニメーション動作中に限りそれら新古のページコンポーネントを共存させられます。アニメーション中はTransitionGroupが生かしてくれる為です。

export default class extends App {
  addEventListener = (node: HTMLElement, done: () => void) => {
    const handle = () => {
      node.removeEventListener('transitionend', handle);
      done();
    };

    node.addEventListener('transitionend', handle);
  };

  render() {
    const {Component, pageProps, router} = this.props;

    return (
      <Container>
        <Provider store={store}>
          <Fade>
            <TransitionGroup>
              <CSSTransition
                key={router.route}
                classNames="fade"
                timeout={1500}
                addEndListener={this.addEventListener}
              >
                <Component {...pageProps} />
              </CSSTransition>
            </TransitionGroup>
          </Fade>
        </Provider>
      </Container>
    );
  }
}

ちなみにFadestyled-componentsになります。これで.fade-<suffix>クラス名を使いアニメーションを実装します。

import styled from 'styled-components';

const Fade = styled.div`
  .fade-enter {}
  .fade-enter-active {}
  .fade-enter-done {}
  
  .fade-exit {}
  .fade-exit-active {}
  .fade-exit-done {}
`;