102
100

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

React-Router v4を使って認証状態でリダイレクトする処理

Last updated at Posted at 2018-02-05

ログインが完了したらトップページにリダイレクト、未ログインで認証が必要なページにアクセスしたらログインページへリダイレクト、という処理がある。
react-routerのv4でルーティングするとこんな形である。

App.js
import React, {Component} from 'react'
import {
  BrowserRouter as Router,
  Route, Switch
} from 'react-router-dom'

import Auth from './containers/Auth'
import Top from './containers/Top'
import Login from './containers/Login'
import Signup from './containers/Signup'
import Page from './containers/Page'

class App extends React.Component{
  render(){
    return(
      <Router>
        <Switch>
          <Route exact path="/login" component={Login}/>
          <Route exact path="/signup" component={Signup}/>
          <Auth>
            <Switch>
              <Route exact path="/" component={Top}/>
              <Route exact path="/page" component={Page}/>
            </Switch>
          </Auth>
        </Switch>
      </Router>
    )}
}

export default App

このとき、Authコンポーネントでは

  1. 認証済みなら何もせず、配下のルーティングに処理をプロキシする(バケツリレーする)
  2. 認証がされていない(未ログイン)なら /login ページにリダイレクトする
    ということをする。
    stateの props.currentUser.isLoggedIn に認証状態を保持しているとして、
components/Auth.js
import React from 'react'
import { Redirect } from 'react-router-dom'

const Auth = (props) => (props.currentUser.isLoggedIn ? props.children : <Redirect to={'/Login'}/>)

export default Auth

結果は非常にシンプルなのだが、1. のバケツリレーがうまくいかず手間取った。NG集としては、

const Auth = (props) => (props.currentUser.isLoggedIn ? <Route children={props.children} /> : <Redirect to={'/Login'}/>)
const Auth = (props) => (props.currentUser.isLoggedIn ? <Route {...props} /> : <Redirect to={'/Login'}/>)

のように、プロキシのためにRouteコンポーネントを介すべきと思っていたら、これでは認証後のページでリダイレクトループが発生してしまう。props.children自体が、App.jsでAuthコンポーネントでラップしているSwitchコンポーネントだと気づいてうまくいった。
なお、Authコンポーネントの直下は単一のコンポーネントにしておく必要がある。今回はSwitchコンポーネントが該当する。バケツリレーするprops.childrenが直下に複数のコンポーネントを持ってしまうと、renderされるコンポーネントは単一の要素でなければいけないというreactの制約に怒られてしまうからだ。

102
100
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
102
100

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?