Reactの身内向けチュートリアル（その３）


Vue.全盛の中、社内メンバー向けのReactの簡単なチュートリアル。

## シリーズ

* [その１：create-react-appの簡単な使い方とファイル構成](https://qiita.com/zaburo/private/99dc965d273f1922deae)
* [その２：簡単なページの作成（共通パーツ化含む）とreact-routernによるルーティング](https://qiita.com/zaburo/private/07182451cc346071b358)
* [その３：簡易認証機能（ログイン・ログアウト）の追加](https://qiita.com/zaburo/private/69fb5352158a9c281aa8)（この記事）

## その３の概要

* ログイン・ログアウト機能をつけ、ログイン済でなければサイトを見えなくします
* 会員ページや管理画面等での利用を想定したものです
* 認証処理は仮のものとします。
* 認証はlocalStorageにlogin=trueというようなフラグがあるかないかで判断するようにします

## ログインページの追加

まずはログインページを作成します。
今回は見た目のみ作成し、ボタンをクリックしたらlocalStorageにlogin=trueとなるような情報を書き込み、Homeにリダイレクトするようにします。

```js:Login.js
import React from 'react';
import { withRouter } from 'react-router-dom';

class Login extends React.Component {

    handleLogin = () => {
        localStorage.setItem("login", "true");
        this.props.history.push("/");
    }

    render() {
        return (
            <div style={{ background: "#eee", height: 200, width: 300, margin: '100px auto', textAlign: 'center', padding: 30 }}>
                <h3>ログイン</h3>
                ID: <input type="text" style={{ marginTop: 10 }} /><br />
                PW: <input tppe="text" style={{ marginTop: 10 }} /><br />
                <button style={{ marginTop: 10 }} onClick={() => this.handleLogin()}>ログイン</button>
            </div>
        );
    }
}

export default withRouter(Login);
```

## 認証機能の実装（仮）

次に認証機能を実装します。localStorageにlogin=trueのフラグ情報があればHomeを表示し、なければ/loginにリダイレクトさせる機能になります。

```js:Auth.js
import React from 'react';
import { Redirect } from 'react-router-dom';

class Auth extends React.Component {
    render() {

        let loginStatus = localStorage.getItem("login");

        if (loginStatus === "true") {
            return this.props.children;
        } else {
            return <Redirect to="/login" />
        }
    }
}

export default Auth;
```

## ログアウト機能の追加

ログアウト機能が無いのでナビゲーションにLogoutボタンを追加し、ログアウト機能を実装します。
ログアウトはlocalStorageのフラグ情報をlogin=falseとすることで実現させます。

```diff:Nav.js
import React from 'react';
import { NavLink, withRouter } from 'react-router-dom';

class Nav extends React.Component {

+    handleLogout = () => {
+        localStorage.setItem("login","false");
+        this.props.history.push("/");
+    }

    render() {
        return (
            <nav style={{ background: "#666" }}>
                <ul style={{ display: 'flex', listStyle: 'none' }}>
                    <li style={{ margin: 10 }}><NavLink exact to="/" style={{ color: "#fff", textDecoration: 'none' }} activeStyle={{ color: '#aaf' }}>Home</NavLink></li>
                    <li style={{ margin: 10 }}><NavLink exact to="/about" style={{ color: "#fff", textDecoration: 'none' }} activeStyle={{ color: '#aaf' }}>About</NavLink></li>
+                    <li style={{ margin: 10 }}><span style={{ color: "#fff", cursor: 'pointer' }} onClick={() => this.handleLogout()}>Logout</span></li>
                </ul>
            </nav>
        );
    }
}

export default withRouter(Nav);
```

## ルーティングの設定

では、上記が連携して動くようにApp.jsの記述を変更します。
\<Auth>\</Auth>で囲まれた部分に認証がかかります。わかりやすいですね。

```js:App.js
import React from 'react';
import { BrowserRouter, Route, Switch, NavLink } from 'react-router-dom';

//import screens
import Home from './screens/Home';
import About from './screens/About';
import Login from './screens/Login';

//Auth
import Auth from './Auth';

class App extends React.Component {
     render() {
          return (
               <BrowserRouter>
                    <Switch>
                         <Route exact path="/login" component={Login} />
                         <Auth>
                              <Switch>
                                   <Route exact path="/" component={Home} />
                                   <Route exact path="/about" component={About} />
                                   <Route render={() => (<p>Page not found.</p>)} />
                              </Switch>
                         </Auth>
                    </Switch>
               </BrowserRouter>
          );
     }
}

export default App;
```

### 動作確認

yarn startさせて動作確認します。

まずはログイン。

![スクリーンショット 2019-11-14 12.43.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/c20c8550-5f10-f4ec-9560-ae454d3ffec6.png "スクリーンショット 2019-11-14 12.43.53.png")

そして、ログイン後のページ。


![スクリーンショット 2019-11-14 12.44.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/b4655935-d3b9-c03f-470a-5a0099fabcd1.png "スクリーンショット 2019-11-14 12.44.00.png")

ログアウトが正常に機能しているかや、ログアウト時に/about等にアクセスした際、ブロックされるか（loginにリダイレクトされるか）等を確認しましょう。

## その３のおさらい

* react-routerを利用した未認証・認証済み時の切り分けについておさらいしました。

## 予定

今後、下記のコンテンツを追加する予定。

* Reduxを利用した値、関数の共有
* Firebaseとの連携（Auth, Hosting, functionsを利用したForm設置等）
  * Hostingにホスティングするのは[こちら](https://qiita.com/zaburo/items/8d9b631faf11b8a99a9d)をどうぞ。
* .envの利用