
練習のためにmockAPIを使用したログイン実装に変更し、かつ、ログイン済みか否かで見れるコンテンツを変えられるようにしました !
こんにちは。はるです。
現在、所属している「もりけん塾」でJavaScriptのハンズオン課題 に取り組み、レビューをいただいています。
今日は、課題35 についてアウトプットをしていきます。
(前回までのアウトプットは、こちらです。)
実装する過程で学んだことを、学習ノートとして記録していきます。
認識の間違えている箇所がありましたら、お問い合わせからご指摘いただけるとうれしいです。
JavaScript課題35の仕様
今回は仕様の変更があり、元々ローカルストレージで実装していたログイン機能を、mockAPIからのデータを取得・照合する方法に変更しました。
【旧仕様】
- ログイン済みのユーザーが見れるコンテンツとそうではないユーザーが見れるコンテンツです
- APIでユーザーに関するmeというエンドポイントのAPIを作り、 そこにはisAuthorizationのようなフィールドがあり、
- trueだったらログイン済みなページ ログイン済みなページでは課題のyahooページのコンテンツを表示して何かログイン済みユーザー特有のコンテンツに変更してください
- この場合ログインボタンの文言は「マイページ」となります
- falseなら 通常の作成済みのyahooを模したコンテンツが表示され ログインボタンが置いてあり、ページに遷移します
【変更点】
1️⃣ isAuthorizationは廃止。
2️⃣ ログインページでログイン時に「mockAPIのユーザー情報」と照合して、合っていればその情報の中にある”userId”をtokenとしてローカルストレージに保存する。
3️⃣ index.htmlは非ログインユーザーが見るページで、アクセス時にローカルストレージにtokenがあれば、ログインユーザー向けページ logged-in.htmlに遷移する
※会員登録ページの流れは変更なし。フォームに入力された情報は登録時にlocalStorgeに保存される。→ その情報でログインするという仕様がなくなる。mockAPIの情報と照合するように変更された。
(もりけんさんのJavaScriptハンズオン課題より)
JavaScript課題35の学習記録
ログイン済みユーザー向けのページと、非ログインユーザー向けのページを作成
index.html
ユーザーが最初にアクセスするページをindex.htmlとして、こちらは非ログインユーザー向けページにしました。
logged-in.html
ログインしているユーザーが見れるページとしてlogged-in.htmlを新規作成しました。
mockAPIを使用してログイン機能を実装する
【Before】
① 会員登録で入力したIDやパスワードをローカルストレージに保存
② ログイン画面で入力した値と、ローカルストレージの値を照合して正しければ、index.htmlに遷移。
【After】
① 会員登録の挙動は変わらず
② ログイン時にmockAPIのデータを取得して、入力値と照合して正しければ、logged-in.htmlに遷移。
mockAPI で模擬APIの作成
簡単に模擬APIを作成できるサービスです。
簡易APIを作成して、実際にデータをfetch(GETメソッドやPOSTメソッドも実際に使用できる)することができます。key, valueに関する設定をすれば、簡単にデモデータを用意してもらえるのでとても便利でした。
丁寧なドキュメントもあり、とても理解しやすいです。
今回は、usersという名前の resoueceを作成、API endpointを生成しました。
// mockAPIで作成してもらったユーザーに関するデモデータ
[
{
"name": "Ruecker",
"email": "Dakota.Hartmann20@example.com",
"password": "NaHtsFAqPT1_OwK",
"userId": "1bc3e7fafee51ea4edd9fbca",
"id": "1"
},
{
"name": "Hamill",
"email": "Hank_Kris@example.org",
"password": "CbZac0M6H57IV97",
"userId": "f8daa6cbbb6afc18acfd21a3",
"id": "2"
},
{
"name": "Botsford",
"email": "Tyreek3@example.net",
"password": "NgHK41c1rxiBu9g",
"userId": "4d980f91eecaccdb6dab066c",
"id": "3"
},
{
"name": "Dicki",
"email": "Lane20@example.net",
"password": "cW3SfU2Lkfb1Yfm",
"userId": "f612ba1c0c5ccf45c0f57e97",
"id": "4"
},
{
"name": "Dicki",
"email": "Demario_Hoppe16@example.org",
"password": "fLDg1A3Tj2qeNsH",
"userId": "259c2dfaca8f1eedcc5dbfb0",
"id": "5"
}
]
データをfetchする
const url = "https://652dc444f9afa8ef4b27cca3.mockapi.io/users"; //mockAPI
// ユーザーに知らせたいテキストを出力
const displayInfo = (target, error) => {
const p = document.createElement("p");
p.textContent = error;
target.appendChild(p);
};
// エラーの情報を出力
const displayErrorStatus = (target, response) => {
const p = document.createElement("p");
p.textContent = `${response.status}:${response.statusText}`;
target.appendChild(p);
};
// APIからデータをfetchする汎用的な関数
const fetchData = async (api) => {
try {
const response = await fetch(api);
if (response.ok) {
return await response.json();
} else {
console.error(`${response.status}:${response.statusText}`);
displayErrorStatus(errorArea, response);
}
} catch (error) {
displayInfo(errorArea, error);
}
};
// 登録ユーザーデータを取得するための関数。ここでAPIのurlを引数で渡す。
const fetchRegisteredData = async () => {
const data = await fetchData(url);
if (!data) return;
if (data.length) {
return data;
}
};
これで、先ほど記載したjsonデータが取得できます。
fetchしたデータと、ログイン画面で入力したinputの値を照合する
const userIdOfInput = document.querySelector(".js-form-userid");
const passwordOfInput = document.querySelector(".js-form-password");
const checkToRegistered = async () => {
const registeredUsers = await fetchRegisteredData();
const user = registeredUsers.find(user => user.name === userIdOfInput.value || user.email === userIdOfInput.value);
if (user && user.password === passwordOfInput.value) {
return { token: user.userId, ok: true, code: 200 };
} else {
throw new Error({ ok: false, code: 401 });
}
}
APIから登録ユーザーのデータを取得します。
const registeredUsers = await fetchRegisteredData();
inputに入力したユーザーID(名前かメールアドレス)が、APIから取得したjsonデータに合致するものがあるか調べます。
const user = registeredUsers.find(user => user.name === userIdOfInput.value || user.email === userIdOfInput.value);
{
"name": "Adams",
"email": "Granville83@example.org",
"password": "3W7j0bv11xf4odx",
"userId": "be29fa5ed5ca3ef7f2633b09",
"id": "4"
},
{ token: user.userId, ok: true, code: 200 }というオブジェクトを返します。
{ ok: false, code: 401 }というエラーオブジェクトを投げます。
if (user && user.password === passwordOfInput.value) {
return { token: user.userId, ok: true, code: 200 };
} else {
throw new Error({ ok: false, code: 401 });
}
ログイン画面で送信ボタンを押した時
ボタンを押すと、login関数が実行されます。
submitButton.addEventListener("click", login);
const login = async () => {
let result;
try {
result = await checkToRegistered();
} catch (error) {
console.error('Login failed:', error);
window.location.href = "./notautherize.html";
return;
}
localStorage.setItem("token", result.token);
window.location.href = "./logged-in.html";
}
login関数では、checkToRegistered関数をtryします。
・エラーが投げられた場合は、consoleにエラーを出しつつ、権限がありませんページに遷移します。
login関数では、try, catchの書き方をレビューで教わりました。
元々書いていたコード
const tryToLogin = async () => {
try {
const result = await checkToRegistered();
localStorage.setItem("token", result.token);
window.location.href = "./logged-in.html";
} catch (rejectObj) {
console.error('Login failed:', rejectObj);
window.location.href = "./notautherize.html";
}
}
ログインユーザーと非ログインユーザーで表示するページを出し分ける
出しわけには、練習で使用しているローカルストレージの値を用いました。
まず、最初にユーザーがアクセスするページは index.html(非ログインユーザー向けページ)です。
// index.html
<head>
<script>if (localStorage.getItem("token")) window.location.href = "./logged-in.html";</script>
</head>
アクセスした時にローカルストレージのtokenをチェックし、tokenがある(=ログイン済み)ならばログインユーザー向けのページに遷移します。
logged-in.html(ログイン)でも、アクセス時にtokenの有無をチェックして、ない場合は非ログインユーザー向けのページに遷移するようにしています。
<script>if (!localStorage.getItem("token")) window.location.href = "./index.html";</script>
コード
lesson35のリンクから実際の挙動を確認できます。
ログインページにて、jsonデータのユーザーどれかの情報を入力すると、ログイン済みユーザー向けのページ(logged-in.html)に遷移することが確認できます。
//
学習に使用している本は、JavaScript本格入門・独習JavaScriptです。
あとがき
もりけんさん(@terrace_tec)お忙しい中レビューいただきありがとうございました!
仕様の変更があり、実装も手探りで進めていた部分が大きく、粒度を分けたPRにできなかったのは反省です。でも、やりたいことを実装することができ、try, catchの部分でレビューをいただけて大変勉強になりました !
今日は以上です。
//
【もりけん塾で勉強しています】
もりけんさん(@terrace_tec)のHPはこちら