⚡
Remixでページ遷移の時にprogress bar(インスタ風)を表示させる
next.JSの場合はライブラリが存在しますが、remixはまだオープンソースに公開されたばかりなので、ここら辺のライブラリがまだ充実してない感じですよね、結構探してもあまり情報が出て来なかったので、自分で公式documentationを読みながら多分こうしたらいけるであろう方法で作ってみたので、シェアしておきたいなと思います。
※ remixもまだ触ったばかりなので、詳しい方がいたらコメント頂けると助かります🙌
試したこと
-
History API
remixはnextjsと違ってページが再読み込みされるみたいなので、ブラウザーのhistory API
にListenerを登録しておいて、ロジックを実装するといった方法ではだめでした。
どうする
公式を探っていたら、useTransition
というhookがありました。
formを送信した後の判定に使ったりするみたいですが、もう少し詳しく見てみるとhookで帰ってくる値 trasnsition.state
にいくつの状態があるみたいです👇。
- idle - There is no transition pending.
- submitting - A form has been submitted. If GET, then the route loader is being called. If POST, PUT, PATCH, DELETE, then the route action is being called.
- loading - The loaders for the next routes are being called to render the next page.
正に loading
ですね!
実装
そのままroot.tsx
に処理追加します。
root.tsx
import {
Links,
LiveReload,
Meta,
Outlet,
Scripts,
ScrollRestoration,
useTransition,
} from '@remix-run/react';
import ProgressBar from './components/ProgressBar';
export default function App() {
const transition = useTransition(); // 👈ここ
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
</head>
<body>
<Outlet />
<ScrollRestoration />
<Scripts />
{process.env.NODE_ENV === 'development' && <LiveReload />}
{transition.state === 'loading' && <ProgressBar />} // 👈ここ
</body>
</html>
);
}
おまけ
web版のインスタグラム風のprogress barの実装(emotion使っています)
ProgressBar.tsx
import { css, keyframes } from "@emotion/css";
const postDiverAnimation = keyframes`
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
`;
const progressInAnimation = keyframes`
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
`;
const ProgressBar = () => (
<div
className={css`
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
height: 3px;
background: #27c4f5
linear-gradient(to right, #27c4f5, #a307ba, #fd8d32, #58c322, #27c4f5);
width: 100%;
background-size: 200% 200%;
animation: ${postDiverAnimation} 2s linear infinite,
${progressInAnimation} 1s ease-in-out;
`}
></div>
);
export default ProgressBar;
インスタグラムは👇こんなに感じですね。
Discussion