react-routerでページ遷移時アニメーション実装

概要

ページ遷移時スライドやフェードなどアニメーションを追加します。 ReactCSSTransitionGroupによってCSSアニメーション実装です。 locationの変化によってアニメーションを入れるかどうかを決めます。

実装

App.jsx

const HORIZONTAL_SLIDE_TRANSITION_PAGES = new RegExp([
  "/abc",
  "/def",
].join("|"));
const PAGE_TRANSITIOM_DURATION = 300;

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { pageTransition: "none" };
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.location !== nextProps.location) {
      if (HORIZONTAL_SLIDE_TRANSITION_PAGES.test(nextProps.location.pathname)) {
        this.setState({ pageTransition: "slide-up" });
      }
      if (HORIZONTAL_SLIDE_TRANSITION_PAGES.test(this.props.location.pathname)) {
        this.setState({ pageTransition: "slide-down" });
        setTimeout(() => {
          this.setState({ pageTransition: "none" });
        }, PAGE_TRANSITIOM_DURATION);
      }
    }
  }

  render() {
    const { location } = this.props;
    const { pageTransition } = this.state;
    const isPageTransition = pageTransition !== "none";

    return (
      <ReactCSSTransitionGroup
        transitionName={pageTransition}
        transitionEnterTimeout={PAGE_TRANSITIOM_DURATION}
        transitionLeaveTimeout={PAGE_TRANSITIOM_DURATION}
        transitionEnter={isPageTransition}
        transitionLeave={isPageTransition}
      >
        <Switch location={location}>
          <Route path="/abc" component={AbcPage} />
          <Route path="/def" component={DefPage} />
          <Route path="/ghi" component={GhiPage} />
          <Route path="/" component={TopPage} />
        </Switch>
      </ReactCSSTransitionGroup>
    );
  }
}

styles.css

.slide-up-enter {
  position: absolute;
  width: 100%;
  transform: translateY(100vh);
  z-index: 10;
}

.slide-up-enter.slide-up-enter-active {
  transform: translateY(0);
  transition: transform 300ms cubic-bezier(0.14, 0.68, 0.36, 1);
}

.slide-down-leave {
  position: absolute;
  top: 0;
  transform: translateY(0);
  width: 100%;
  z-index: 10;
}

.slide-down-leave.slide-down-leave-active {
  transform: translateY(100vh);
  transition: transform 300ms cubic-bezier(0.14, 0.68, 0.36, 1);
}

参考

https://facebook.github.io/react/docs/animation.html