2018/05/09更新

[フロントエンド] ReactRouter(v4)で、ログインチェック付きのルーティングを行う

このエントリーをはてなブックマークに追加            

こんにちは、@yoheiMuneです。
今日はReact Routerを用いたルーティングにおいて、ページ遷移時にログインチェックを行う方法をブログに書きたいと思います。



目次




対象のバージョン

React Routerはv4以上が対象です。



何がしたいのか

React.jsでアプリケーションを作成した場合に、ルーティングはReact Routerで行うことがほとんどではないでしょうか。管理画面やマイページなどのログインが必要なページを開発している場合、画面遷移時にログインチェックを行いたいという要件は良くあります。そして、ログイン済みの場合にのみそのページを表示、未ログインならログインページにリダイレクトしたい、といった振る舞いを実装する場面があります。
それをReact Routerでどのように実現するのか、についてブログを書きたいと思います。

また、他のブログでは同期的なログインチェックのサンプルが見つかりますが、サーバーへの問い合わせを行うなどの非同期的なログインチェックのコードはあまりありません。今回はそのケースにも対応した実装方法を紹介します。



ログインチェック付きのルーティングを行う

例えば以下のようなルーティング定義があったとします。
<Switch>
  <Route path="/login" component={Login}/>
  {/* /dashboardはログイン済にのみ表示したい  */}
  <Route path="/dashboard" component={Dashboard}/>
</Switch>
/dashboard遷移時にはログインチェックをしてから表示したい仕様です。
これを実現するために、ログインチェック用のルーティングを行うコンポーネントを作成します。


ログインチェックを行うルーティングコンポーネントを作成

ここではPrivateRouteという名前で、コンポーネントを新規に作成します。
import React, { Component } from 'react'
import { Route, Redirect } from "react-router-dom"
import AuthService from './services/AuthService'  // ログインチェックを行うサービス.

class PrivateRoute extends Component {

  constructor(props) {
    super(props)
    this.authApi = new AuthService()
    this.state = {
      // ログインチェックが終わるまで、ローディングを表示.
      loading : true,
      // ログインチェック結果.
      isAuthenticated : false
    }
  }

  async componentDidMount() {

    // ログイン状態のチェック.
    // ここではasync/awaitで非同期に処理しているが、同期処理でもOK.
    const ok = await this.authApi.checkLogin()

    // 結果を反映.
    this.setState({
      loading : false, 
      isAuthenticated : ok
    })
  }

  render() {

    // ルーティング情報を取得.
    const { component : Component, ...rest } = this.props

    // ログインチェック状態を取得.
    const { loading, isAuthenticated } = this.state

    // ログインチェック前なら、ローディングを表示.
    if (loading) {
      return <div className="loading">Loading...</div>
    }

    // ログインチェック後はルーティング処理を行う.
    return (
      <Route {...rest} render={() => {
        // 未ログインなら、ログイン画面にリダイレクト.
        if (!isAuthenticated) {
          return <Redirect to={{ pathname: '/login', state: { from: this.props.location } }} />
        }
        // ログイン済なら、指定されたコンポーネントを表示.
        return <Component {...this.props} />
      }}
      />
    )
  }
}

export default PrivateRoute
少し処理が長いですが、ログインチェックをしたのちに、ルーティングを行うようにしています。

async/await構文が少し不安な方は「[フロントエンド] ES7のasync/awaitを使って、Promiseを同期的に処理する」をご参照ください。


PrivateRouteを利用する

上記で作成したPrivateRouteは、以下のように利用します。
import PrivateRoute from './PrivateRoute'  // インポートを追加

// 中略

<Switch>
  <Route path="/login" component={Login}/>
  {/* PrivateRouteに変更 */}
  <PrivateRoute path="/dashboard" component={Dashboard}/>
</Switch>
これでログインチェック付きのルーティングを行うことができるようになりました。



参考資料

今回の実装を行うのに、以下のstack overflowを参照しました。ありがとうございます。

reactjs - Authenticate async with react-router-v4 - Stack Overflow



最後に

React.jsの開発では、このようなTipsをたくさん習得することが開発効率アップのポイントかなと思います。React.jsについては今後もブログを書きたいと思いますので、ぜひお付き合いください ^ ^。

最後になりますが本ブログでは、フロントエンド、サーバー、Swift、PHP、Node.js、Python、Java、Linux、インフラ、Go言語、機械学習、などの技術トピックを発信をしていきます。「プログラミングで困ったその時の、解決の糸口に!」そんな目標でブログを書き続けています。ぜひ、本ブログのRSSTwitterをフォローして貰えたら嬉しいです ^ ^

最後までご覧頂きましてありがとうございました!





こんな記事もいかがですか?

[取り組み] フロントエンドでコーディングスピードをアップさせる6つの方法!と思って書いてたら30個も書いちゃった。
[フロントエンド] フロントエンドの入社試験99問!難しいですよ〜w。
[フロントエンド] Webページを表示するテストの際に、通信速度を3Gに制限して表示してみよう
[フロントエンド] スマホ実機でのデバッグ手段を増やす!Macのプロキシを利用して、通信内容を確認する。
[フロントエンド] Chrome 35 Beta の変更点。Touch制御、新しいJavaScript機能、プレフィックスなしのShadowDOM
[フロントエンド]複数アカウントでのテストには、Chromeのユーザー管理を使って、Cookieを切り替えると便利
[フロントエンド] Chrome36βが出た。変更点など。element.animate、HTML Imports、Object.observe、他。
RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。