Next.js + Framer Motion でページ遷移アニメーションを実装したいが、「exit」が走らない
記事のコンセプト
この記事は「Framer Motionでページ遷移のアニメーションを作りたいが、exitの処理が動かない!」とお困りの方に向けた記事です。
スタックオーバーフローでも同じ悩みの質問がありましたが、解決している記事は見かけませんでした。
同じ悩みを持った同士の手助けができるよう、備忘録として残します。
結論
NEXT以外のLinkコンポーネントを使っているから。
かもしれません。
開発環境
- Next.js
- TypeScript
- MUI
- Framer Motion
経緯
Next.jsでページ遷移時、フェードアウト→フェードインするアニメーションを「Framer Motion」で作りたいなーと思った。
そこでこちらの記事を参考にさせて頂きながら実装してみた。
// _app.tsx
import { AnimatePresence } from "framer-motion";
const MyApp = ({ Component, pageProps, router }: AppProps) => (
<AnimatePresence exitBeforeEnter>
<Component key={router.asPath} {...pageProps} />
</AnimatePresence>
);
export default MyApp;
// レイアウト用のファイル
export default function Layout(props: Props) {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<Header />
// ヘッダー直下に配置
<motion.div
initial={{ opacity: 0, y: 10 }} // 初期状態
animate={{ opacity: 1, y: 0 }} // マウント時
exit={{ opacity: 0, y: 10 }} // アンマウント時
transition={{
duration: 0.5,
}}
>
<Container>
{props.children}
</Container>
</motion.div>
</ThemeProvider>
);
}
これでページ遷移するたびに、0.5秒掛けて下にフワッとフェードアウトして、フワッとフェードインするはず。
わくわく。
しかし、そこでハマった。
「exit」が動作しない。
ページ遷移した際「initial」「animate」は意図した通り作動し、下からフワッと表示される。
だが、「exit」のアニメーションが作動しているようには見えなかった。
つまり、パッと消えてフワッとなるのだ。
なんでだ。。
記述場所を変えてみたり、公式ページや英語の記事を読んだりしながらいろいろ試行錯誤。
そして約1時間後、何とか原因を突き止められた。
原因考察
私の場合
MUIのLinkコンポーネントを使っていたから。
でした。
- import { Link } from "@mui/material";
+ import Link from "next/link";
偶然、Next.jsのリンクコンポーネントで試してみたら、
思った通りのフワッと消えてフワッと現れるアニメーションが実現しました。
奇跡。
MUIのLinkコンポーネントはアイコンとか設定し易いという理由で使っていましたが、どうやら「Framer Motion」と相性が悪かったらしいです。
これがexitが走らない全ての原因なのかはわかりませんが、とにかく私のアニメーションは動きました。
あとがき
今後からはNext.jsのリンクコンポーネントを使っていくことにします。😅
また、他にも同じ名前のコンポーネントが他にもあった場合、Next.jsで提供されているものを優先して使って行こうと思います。
意図しない挙動をした時はぜひ、コンポーネントの提供元を変えることを試してみてください。
Discussion