タスク管理ツールをReact + ASP.Coreで作る017クライアントに登録・認証機能を追加

### ガイド
全体Index：[タスク管理ツールをReact + ASP.Coreで作る - Index](https://qiita.com/mosuma/items/88e40dc44e7bff1a54d8)

## 認証機能追加の一連の流れ
- [016サーバーサイドに認証機能関連のクラス追加](https://qiita.com/mosuma/items/728f501bcc7e54352fb8)
- 017クライアントにユーザー登録・ログイン画面と処理を追加(本記事)
- [018認証トークン関連機能をサーバー・クライアント双方に追加](https://qiita.com/mosuma/items/035967eb98259bbd4934)
- [019認証有無に従い制御を実施する機能を追加](https://qiita.com/mosuma/items/82ae859577ab676c06bc)
- [020認証機能をリファクタリング](https://qiita.com/mosuma/items/cf50dc4136fe06233412)
- [021認証状態に従い画面表示を切り替え](https://qiita.com/mosuma/items/5b7ed9431633800e7cc6)

# 概要
[前回](https://qiita.com/mosuma/items/728f501bcc7e54352fb8)までで、サーバーサイドに認証機能関連のパッケージとコードの追加を実施しました。
サーバー側で認証状態による各APへのアクセス制御をまだ組み込んでいないので、今のところ動作に違いはありません。またアクセス制御を有効にする前にクライアント側に「ユーザー登録」、「ログイン」などの機能を作っておく必要があるので、今回はそれらを実装していきます。




# 構築

## 本記事で実施する内容のサマリー

- 登録・ログインのための入力・結果取得用の機能追加。


# コード追加

以下の場所にコードを追加します。

![](https://storage.googleapis.com/zenn-user-upload/771925a7e2e7-20220506.png)

### Login.tsx
```diff_tsx:Login.tsx
import React, { SyntheticEvent, useState } from 'react';

const Login = (
    ) => 
{
    
    const [name, setName] = useState('');
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [resultcode, setResultcode] = useState(0);
    const [resultTitle, setResultTitle] = useState('');



    const submit = async (e: SyntheticEvent) => {
        e.preventDefault();
        const response = await fetch('https://localhost:5001/account/login',
        {
            method : 'POST',
            headers:{'Content-Type' : 'application/json'},
            body: JSON.stringify({
                email,
                password
            })
        });
        const content = await response.json();
        const status = await response.status

        setResultcode(status);
        setResultTitle(content.title);
        if(status==200){
            setName(content.username);

        }

    }

    
    return (
        <>
        <form onSubmit={submit}>
            <h2>Sign in</h2>

            <ul>

                <li>
                    <label>email</label>
                    <input type="email" placeholder="name@example.com" required 
                        onChange = {e => setEmail(e.target.value)}            
                    />
                </li>

                <li>                    
                    <label>password</label>
                    <input type="password" placeholder="Password" required 
                        onChange = {e => setPassword(e.target.value)}            
                    />
                </li>
            </ul>

            <button type="submit">Sign in</button>

        </form>
        
        <h2>Response</h2>

        <ul>
            <li>
                {resultcode!=0 && <>{resultcode==200 ? <>Login Success</> : <>Login Fail</>}</>}
            </li>

            <li>
                {resultcode==200 && <>Name:{name}</>}
            </li>

            <li>
                {resultcode!=0 && <>Code:{resultcode}</>}
            </li>

            <li>
                {resultcode!=0 && <>msg:{resultTitle}</>}
            </li>
        </ul>
        </>
    );

}

export default Login;
```

### Register.tsx
```diff_tsx:Register.tsx
import React, { SyntheticEvent, useState } from 'react';

const Register = () => {
    
    const [username, setName] = useState('');
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [resultcode, setResultcode] = useState(0);
    const [resultTitle, setResultTitle] = useState('');

    const submit = async (e: SyntheticEvent) => {
        e.preventDefault();
        const response = await fetch('https://localhost:5001/account/register',
        {
            method : 'POST',
            headers:{'Content-Type' : 'application/json'},
            body: JSON.stringify({
                email,
                username,
                password
            })
        });
        const content = await response.json();
        const status = await response.status

        setResultcode(status);
        setResultTitle(content.title);
    }

    
    return (
        <>
        <form onSubmit={submit}>
            <h2>Register</h2>

            <ul>
                <li>
                    <label>Name</label>
                    <input placeholder="Name" required
                        onChange = {e => setName(e.target.value)}            
                    />
                </li>

                <li>
                    <label>email</label>
                    <input type="email" placeholder="name@example.com" required 
                        onChange = {e => setEmail(e.target.value)}            
                    />
                </li>

                <li>                    
                    <label>password</label>
                    <input type="password" placeholder="Password" required 
                        onChange = {e => setPassword(e.target.value)}            
                    />
                </li>
            </ul>

            <button type="submit">Register</button>

        </form>
        
        <h2>Response</h2>

        <ul>
            <li>
                {resultcode!=0 && <>{resultcode==200 ? <>Register Success</> : <>Register Fail</>}</>}
            </li>

            <li>
                {resultcode!=0 && <>Code:{resultcode}</>}
            </li>

            <li>
                {resultcode!=0 && <>msg:{resultTitle}</>}
            </li>
        </ul>
        </>
    );

}

export default Register;
```

### App.tsx

```diff_tsx:App.tsx

import React from 'react';
import logo from './logo.svg';
import './App.css';
import { WeatherForecast } from './WeatherForecast';
+import Register from './Account/Register';
+import Login from './Account/Login';

function App() {
  return (
    <div>
+      <Login />
+      <hr />
+      <Register />
+      <hr />
      <WeatherForecast />
    </div>
  );
}

export default App;
```


## 動作確認
結果をもとに画面遷移させるなどの高度な処理は行わず、同一画面で「登録」と「ID・パスワードの結果確認」を行うための構成になっています。

実行させると、以下の様に画面が移ります。

登録確認をする前に、WheatherForcastの情報が表示されていることを確認しましょう。
表示されていればサーバーとの通信までは確立していることになります。

![](https://storage.googleapis.com/zenn-user-upload/a5b0e181e17b-20220506.png)


### ユーザー登録

まずはユーザーを登録してみましょう。
登録が成功すると以下のように成功の結果が返ってきます。
ちなみに表示されていませんが、パスワードは"AB234XXX..asf"にしています

![](https://storage.googleapis.com/zenn-user-upload/072f44d8f808-20220506.png)

SQLite拡張が入っていれば、そちらからテーブルを見ることでユーザーが追加されていることを確認できます。
(画像では動作を確認するために本記事で登録した以外にもいくつかユーザーが入っています。)
![](https://storage.googleapis.com/zenn-user-upload/36684cc42d32-20220506.png)


### ログイン成功時
ユーザー登録が成功した際のEメールアドレス・パスワードをログイン画面に入力してみると、以下のような結果になります。

![](https://storage.googleapis.com/zenn-user-upload/fb28b52fc64f-20220506.png)

### ログイン失敗時
登録していないID・間違えたパスワードを入力すると、以下の様に失敗の応答結果が返ってきます(下の画像ではEメールアドレスを間違えています。)

![](https://storage.googleapis.com/zenn-user-upload/8dce65628c11-20220506.png)



今回は以上です。続きは[次回](https://qiita.com/mosuma/items/035967eb98259bbd4934)です


TAG V000-14-00