【React】自動非同期ログインチェックとログイン状態でのみ適用されるルーティングの作り方

 React 上である API に対してログイン状態でなければログインページへ自動でリダイレクトされ、ログイン状態でなければ移動できないルーティング(認証が API のみの場合、URL 直叩きによって具体的なデータ抜きの React 上のページを見れる様なコードを生みやすいです)を実現します。
 この処理はログインページが React で作られている場合にログインページ以外のページを骨組みだけでも外部に見せたくない、という要求を満たすのに便利です。認証処理が必要な環境が web ページならばログインページだけを React と別に静的ページで用意し、React を用いるページへのアクセスに認証が必要、とする実現方法もあります。
 これは次で実装できます。

/**
 * ログイン済みならば true,そうでないならば false を返す関数
 * @return {Promise<boolean>}
 */
const getIsAuthenticated = async () => {
  try{
    // API にアクセスして認証済みか確認するなど、何か認証を確認する適当な非同期処理
    const response = await BaseRepository.post('is-auth', {/** トークン等の認証状態を示すデータ */});

    return !!response.data.success;
  }catch(err){
    return false;
  }
};

/**
 * ログイン済みか否かをチェックするフック
 * @return {{isLoading: boolean, setAuthenticated: React.Dispatch<React.SetStateAction<boolean>>, isAuthenticated: boolean}}
 */
const useAuthChecker = () => {
  const [isLoading, setLoading] = React.useState(true);
  const [isAuthenticated, setAuthenticated] = React.useState(false);
  // アプリ(厳密にはこのフックを使っているコンポーネント)がマウントされた際に一度だけログイン済みか否かを確認
  React.useEffect( () => {
    getIsAuthenticated().then(auth => {
      // ログイン済みか否かの確認が終われば、それを state にセット
      setAuthenticated(auth);
      setLoading(false);
    });
  },[])
  return {
    isLoading,
    isAuthenticated,
    setAuthenticated,
  }
}

/**
 * ログイン済みか否かでルーティングを切り替えるルーター
 * @return {JSX.Element}
 */
const AuthRouter = () => {
  const {isLoading, isAuthenticated, setAuthenticated} = useAuthChecker();

  // ログイン済みか否かを確認している間は具体的な画面を表示せず、ローディングのみを表示
  if(isLoading){
    return (<div>通信中...</div>)
  }

  // ログイン済みか否かを確認できたならば、認証済み用ルーティングかログインページかの分岐を処理する
  return isAuthenticated ? (
    <AppFrame logout={() => setAuthenticated(false)}>{/* ページの大枠。ログアウトボタンを含むコンポーネントを想定 */}
      <Switch>
        <Route path={'/hoge'}><div>ログインした状態のみのルーティング例</div></Route>
        <Route path="*"><NotFound/></Route>{/* NotFound は 404 ページ用コンポーネント */}
      </Switch>
    </AppFrame>
  ) : (
    <Switch>
      <Route path="/login"><LoginPage login={()=>setAuthenticated(true)}/></Route>{/* ログインページ */}
      <Redirect to={{pathname: '/login', state: {from: location}}}/>{/* 認証がまだの状態で/login 以外のページへ移動しようとした場合、/loginへリダイレクト */}
    </Switch>
  )
}

// React 共通の DOM へのマウント
const App = () => <Router><AuthRouter/></Router>;
import ReactDOM from 'react-dom';
ReactDOM.render(<App />, document.getElementById('root'));  

 getIsAuthenticated が認証済みかの API を叩くリポジトリ的関数、useAuthChecker が自動で認証チェックをするためのロジック、AuthRouter が認証状態で姿を変える画面です。
 例では isAuthenticated と三項演算子によって認証状態でのみルーティングを変化させていますが、ユーザー種別などもっと多い分岐にも使えます。分岐を多くする場合はオブジェクトを使ってどの定数の状態のユーザがどのルーティングを使うなどのマッピングを行うと整理しやすいです。
【JavaScript】オブジェクトリテラルをswitch文的に扱う – 株式会社シーポイントラボ | 浜松のシステム・RTK-GNSS開発

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG