react-router-dom ログイン認証の仕組みを実装する
React
+react-router-dom
+TypeScript
でログイン認証の仕組みを実装する方法を紹介します。
以下の仕様で実装します。
未ログイン時
- ログインページにアクセス可能
- 以外のページにアクセス時はログインページに遷移(アクセスしようとしたページの情報は保持しておく)
- ログイン後はトップページまたはアクセスしようとしたページに遷移
ログイン時
- ログインページ以外にアクセス可能
- ログインページにアクセス時はトップページに遷移
- ログアウト後はログインページ遷移
ルーティング設定
まずはログインページとトップページのルーティング設定を行います。
詳しくはReact react-router-domの基本的な使い方で紹介しています。
ログイン時のみ表示したいページ(「認証ルート」と呼ぶことにします)は別ファイルとして管理しています。
route.tsx
import { Route, Switch } from 'react-router-dom';
import { VFC } from 'react';
import Login from './pages/Login';
import AuthenticatedRoute from './AuthenticatedRoute';
const routes: VFC = () => {
return (
<Switch>
<Route path="/login" exact component={Login} />
<AuthenticatedRoute />
</Switch>
);
};
export default routes({});
AuthenticatedRoute.tsx
import { Route, Switch } from 'react-router-dom';
import { VFC } from 'react';
import Home from './pages/Home';
import About from './pages/About';
const AuthenticatedRoute: VFC = () => {
return (
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" exact component={About} />
</Switch>
);
};
export default AuthenticatedRoute;
認証チェックの追加
認証ルートにアクセス時は、ログイン済みかどうかの判定を行い、ログインしていない場合はログイン画面に遷移する必要があります。
以下のコンポーネントを作成し、ログインしていない場合はログイン画面に遷移し、ログイン時は子要素をそのまま表示するようにします。
また、ルートの状態state
にアクセスしようとしたページのパスを保持しておきます。(ログイン後にアクセスしようとしたページに遷移するために必要になります)
(useAuth
は独自に作成した処理です。ログイン状態をboolean
で判定できる方法であれば何でも構いません)
AuthenticatedGuard.tsx
import { useAuth } from './store/auth';
import { FC } from 'react';
import { Redirect, useLocation } from 'react-router-dom';
const AuthenticatedGuard: FC = ({ children }) => {
const { isAuthenticated } = useAuth(); // ログイン済みかどうかのフラグ
const location = useLocation();
return isAuthenticated ? <>{children}</> : <Redirect to={{
pathname: '/login',
state: { from: location },
}} />;
};
export default AuthenticatedGuard;
上記で作成したコンポーネントを認証ルートのコンポーネントにラップします。
route.tsx
import { Route, Switch } from 'react-router-dom';
import { VFC } from 'react';
import Login from './pages/Login';
import AuthenticatedRoute from './AuthenticatedRoute';
import AuthenticatedGuard from './AuthenticatedGuard';
const routes: VFC = () => {
return (
<Switch>
<Route path="/login" exact component={Login} />
<AuthenticatedGuard>
<AuthenticatedRoute />
</AuthenticatedGuard>
</Switch>
);
};
export default routes({});
これでログイン認証のルーティング設定は完了です。