Posted at

react-transition-groupでスライドメニューを作ろうとしたときの備忘録

Reactでフロントエンド開発を行なっていて、画面に動きをつけたいときに便利なライブラリであるreact-transition-group。

今回はこのreact-transition-groupを使って横からニュッと出てくるメニューを作ろうとして躓いたところがあったので、その解決策について備忘録として書いておきます。

やりたいものはこんな感じ。

この記事ではstyled-componentsを使っていますが、Transitionを使った際の解決策としては他のスタイル形式でも変わらないと思います。

バージョン

・typescript: "3.5.3"

・react: "^16.9.0"

・react-transition-group: "^4.2.2"


困ったところ

最初は以下のように実装していました。(挙動に関係ない部分は省略しています。)

interface Props {

children: ReactNode;
open: boolean;
}

export const SlideMenu = (props: Props) => {
return (
<Transition
in={props.open}
timeout={500}
unmountOnExit
>
{state => (
<Inner state={state}>
{props.children}
</Inner>
)}
</Transition>
);
};

const slideWidth = 500;

const Inner = styled.div<{ state: TransitionStatus }>`
position: absolute;
transition: 0.5s;
right: -
${slideWidth}px;
width:
${slideWidth}px;
transform: translateX(
${({ state }) => (state === "entered" ? -slideWidth : 0)}px
);
`
;

unmountOnExitで最初は要素を消しておいて、右側のマイナス位置から左側へ動かすというイメージです。

ただこの設定だと、このように動かし始めが遅く、もっさりした動きになってしまいます。


解決策

ちょっと考えればわかることだったのですが、この現象はTransitionのinがトグルされてからtranslateによる動きが発生するまでが長すぎたことが原因で発生していました。

なので、Transitionコンポーネントのtimeoutを以下のように設定することで解決することができました。

// before

timeout={500}
// after
timeout={{ appear: 0, exit: 500 }}

コンポーネントがマウントされてからTransitionのモーションに移るまでの時間を0に設定しました。

これによってコンポーネントがマウントされてすぐに設定したアニメーションが発動するようになったということになります。


まとめ

地味ながらも忘れやすそうな設定内容だったので、備忘録として残しておきます。

もっとスマートな方法があるかも知れませんが、同じようなところで困っている方のお役に立てれば幸いです。

閲覧いただき、ありがとうございました。