Reactのカスタムフックで認証トークンを扱う方法!初心者でもわかるAPI管理の基本
生徒
「先生、ReactでAPIを使うときに認証トークンが必要って聞いたんですけど、それってどういうことですか?」
先生
「認証トークンは、アプリとサーバーが安全にやりとりするための“鍵”のようなものです。ログインしたユーザーだけが使える秘密のパスのような役割をします。」
生徒
「なるほど!じゃあReactでその認証トークンをどうやって扱えばいいんですか?」
先生
「カスタムフックを作ると便利ですよ。トークンの保存や取得、APIに自動で付ける処理をまとめられます。」
1. 認証トークンとは?
認証トークンとは、ユーザーがログインしたときにサーバーから渡される文字列のことです。英数字のランダムな文字で構成されていて、「この人はログイン済みですよ」と証明してくれます。
例えば、映画館のチケットをイメージしてください。入口でチケットを見せれば入場できるように、サーバーにリクエストを送るときにトークンを一緒に送れば、ログインした人だけが情報を受け取れるようになります。
2. Reactでトークンを保存する場所
Reactで認証トークンを扱うときは、次のような保存方法があります。
- localStorage:ブラウザを閉じてもデータが残る
- sessionStorage:ブラウザを閉じると消える
- Reactの状態管理(useStateやContext):ページを開いている間だけ使う
初心者の方は、まずlocalStorageを使って保存するのが分かりやすいでしょう。
3. カスタムフックでトークンを管理する
次に、認証トークンを管理するカスタムフックを作ってみましょう。保存、取得、削除をひとつにまとめることで、どこからでも簡単に使えるようになります。
import { useState } from "react";
function useAuthToken() {
const [token, setTokenState] = useState(() => localStorage.getItem("token"));
const saveToken = (newToken) => {
localStorage.setItem("token", newToken);
setTokenState(newToken);
};
const clearToken = () => {
localStorage.removeItem("token");
setTokenState(null);
};
return { token, saveToken, clearToken };
}
export default useAuthToken;
このフックを使えば、認証トークンを保存したり削除したりできるようになります。
4. トークンを使ってAPIにアクセスする
次に、保存したトークンを使ってAPIにリクエストを送ってみましょう。トークンはAuthorizationというヘッダーに入れるのが一般的です。
import React from "react";
import useAuthToken from "./useAuthToken";
function App() {
const { token, saveToken, clearToken } = useAuthToken();
const fetchData = async () => {
if (!token) {
alert("ログインしてください");
return;
}
const response = await fetch("https://api.example.com/data", {
headers: {
Authorization: `Bearer ${token}`,
},
});
const data = await response.json();
console.log(data);
};
return (
<div>
<h1>認証付きAPIアクセス</h1>
<button onClick={() => saveToken("dummy-token")}>ログイン</button>
<button onClick={fetchData}>データ取得</button>
<button onClick={clearToken}>ログアウト</button>
</div>
);
}
export default App;
5. トークン管理をカスタムフックで行うメリット
認証トークンをカスタムフックでまとめることで、次のようなメリットがあります。
- どのコンポーネントからでも簡単にトークンを利用できる
- ログイン、ログアウト処理を一元管理できる
- トークンを安全に扱いやすくなる
特に大規模なアプリでは、あちこちでトークン処理を書かなくて済むのでコードがスッキリします。
6. 実際のアプリでの応用例
実際のWebアプリケーションでは、次のような場面で認証トークンを扱います。
- ユーザーがログインしてからマイページを表示するとき
- ネットショップで購入履歴を読み込むとき
- チャットアプリでログイン中のユーザーを識別するとき
どれも「ログイン済みの人しか見られない情報」を守るためにトークンが使われます。これはアプリの安全性を高めるためにとても大切です。
まとめ
ここまで、Reactにおける認証トークンの基本的な概念から、カスタムフックを活用した具体的な実装方法までを詳しく解説してきました。Webアプリケーションの開発において、ユーザーの認証状態を正しく管理し、安全にAPIと通信することは非常に重要なステップです。特にReactのようなフロントエンドフレームワークでは、状態(State)と副作用(Side Effects)を適切に分離して記述することが、コードの保守性を高める鍵となります。
認証トークン管理のポイント再確認
認証トークン、特にJWT(JSON Web Token)などは、一度サーバーから発行されると、その後のリクエストで「自分は誰であるか」を証明する通行証の役割を果たします。この記事で紹介した localStorage を利用する方法は、ブラウザをリロードしてもログイン状態を維持できるため、多くの一般的なWebサービスで採用されている手法です。しかし、セキュリティをより強固にするためには、トークンの有効期限の設定や、セキュアなCookieの利用なども検討の余地があります。
カスタムフックによるロジックの共通化
プログラムを記述する際、同じような処理を何度も書く「重複」はバグの温床になります。Reactのカスタムフック(Custom Hooks)は、まさにこの「ロジックの再利用」を実現するための強力な武器です。今回作成した useAuthToken を使えば、ログインページでも、プロフィール編集ページでも、あるいはヘッダーのログアウトボタンでも、全く同じロジックでトークンを操作することが可能になります。
さらに実践的なサンプルコード:ステータス管理の強化
実際の現場では、トークンがあるかどうかだけでなく、「現在読み込み中なのか」や「認証エラーが起きたのか」といった状態も管理する必要があります。少し応用して、認証状態をより詳細に扱うための実装例を見てみましょう。
import { useState, useEffect } from "react";
function useEnhancedAuth() {
const [authToken, setAuthToken] = useState(null);
const [isLoading, setIsLoading] = useState(true);
// 初期化時にローカルストレージを確認
useEffect(() => {
const savedToken = localStorage.getItem("token");
if (savedToken) {
setAuthToken(savedToken);
}
setIsLoading(false);
}, []);
// ログイン処理用
const login = (newToken) => {
localStorage.setItem("token", newToken);
setAuthToken(newToken);
};
// ログアウト処理用
const logout = () => {
localStorage.removeItem("token");
setAuthToken(null);
};
return {
authToken,
isAuthenticated: !!authToken,
isLoading,
login,
logout
};
}
export default useEnhancedAuth;
この拡張版フックでは、isLoading という状態を追加しています。アプリが起動した瞬間にストレージを確認し、準備ができるまでは「読み込み中」を表示させるといった、ユーザー体験(UX)を考慮した設計が可能になります。
認証情報をアプリ全体で共有する応用
小規模なアプリなら個別のコンポーネントでフックを呼び出すだけで十分ですが、アプリが成長して「ログインしているかどうかでメニューの表示を切り替えたい」といった箇所が増えてきたら、Reactの Context API と組み合わせるのがベストプラクティスです。これにより、コンポーネントの階層に関係なく、どこからでも最新の認証状態にアクセスできるようになります。
API通信時の自動ヘッダー付与
また、毎回 fetch 関数に Authorization ヘッダーを手動で書くのは大変です。実務では axios などのライブラリを使って「インターセプター」という機能を設定し、リクエストを送る直前に自動でトークンを差し込む仕組みを構築することが一般的です。これにより、開発者は認証のことを意識せずに、純粋なデータ取得処理に集中できるようになります。
最後に
ReactでのAPI管理や認証処理は、最初は難しく感じるかもしれません。しかし、一つ一つの役割を分解して「カスタムフック」に閉じ込めることで、驚くほど見通しの良いコードになります。まずは基本となる localStorage への保存と、ヘッダーへの付与から始めてみてください。一歩ずつ理解を深めていけば、複雑な認証システムも自由自在に操れるようになるはずです。
生徒
「先生、まとめまで読んでカスタムフックの便利さがすごくよく分かりました!ロジックを外に出すだけで、App.jsがこんなにスッキリするんですね。」
先生
「そうですね。Reactの真骨頂は『コンポーネント』の再利用性ですが、カスタムフックを使えば『処理そのもの』も使い回せるようになります。認証トークンの管理はその代表例ですよ。」
生徒
「さっきの拡張版コードにあった isLoading も面白いです。これを使えば、ログインチェック中に一瞬だけ未ログイン画面が見えちゃう、みたいなバグも防げそうですね!」
先生
「その通り!細かい配慮がアプリのクオリティを上げます。実際の開発では、トークンが期限切れになった時のエラーハンドリングなども必要になりますが、まずは今の形を完璧にマスターしましょう。」
生徒
「はい!localStorageを直接触るんじゃなくて、フックを通すことでデータの流れが追いやすくなりました。早速、自分のポートフォリオ制作にも取り入れてみます!」
先生
「素晴らしい意気込みですね。もし詰まったら、ブラウザの開発者ツールの『Application』タブを見て、トークンが正しく保存されているか確認しながら進めるといいですよ。応援しています!」