1
/
5

【React(Redux) × Laravel】SPAにおいて、リロード後もログイン状態を保持させたいとき


まあそんな話は置いといて、さっそく本題に移りましょう。

テーマは、React(Redux) × LaravelのSPAにおいて、ページをリロードした後もログイン状態を保持させる方法についてです。

SPAのログイン認証を作った際に発生した問題

実際に僕がReact(Redux) × Laravelでログイン認証機能を作っていたときの話です。

作った機能について簡単に説明します。

まずLaravel側でログインAPIを作り、ログイン成功時はログインしたユーザー情報を返すようにします。

React側ではログイン時にそのAPIを叩く処理と、返り値をstateに入れる処理を作ります。

ログイン状態かログアウト状態かは、このstateにユーザー情報が入っているか否かで識別するので、

つまり、ログインが成功すればstateにユーザー情報が入り、ログイン状態になるという仕組みを作りました。


これでログイン認証機能は完成したと誰もが確信していた。


しかし…

そうです。このログイン認証機能には欠陥があったんです。

ログインが成功してstateにユーザー情報が入ってもページをリロードしたり、一度ページを離れてしまうとstateが初期化されるため、そのたびにログイン状態が消えてしまうんです。

いろいろ考えた結果、一つの解決策にたどり着きました。

結論から言うと、

リロード時にもログイン状態を更新できるAPIを叩けばいいんです。

今回は上記の実現方法を紹介します。


ログイン状態を保持させるロジック

実行環境

・Laravel 9.22.1

・Laravel Sanctum 3.0

・React 17.0.2 (TypeScript)

・Redux Tool Kit 1.8.3

LaravelでのSPA認証はLaravel Sanctumを使います。

ログイン状態のstate管理についてはRedux Tool Kitを使います。

それぞれの導入方法についてはここでは割愛します。


ロジックの説明

ロジックをざっくり説明します。

Laravel側でログインAPIの他に、ログイン中のユーザー情報をGETで取得するAPIを作ります。

React側ではuseEffectを使って、初回レンダリング時にそのAPIを叩き、stateに返り値であるユーザー情報を入れる処理を作ります。

そうすることで、リロードしても毎回ユーザー情報がstateに入るので、ログイン状態が保持されるという仕組みです。


実装してみよう

Laravel側の実装

まずはLaravel側から実装していきます。

とは言っても、今回導入しているLaravel Sanctumには、ログイン中のユーザー情報を取得するAPIがデフォルトで実装されています。

routes/api.phpを見てみましょう。

// api.php

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

このAPIを叩けば、ログイン中のユーザー情報が取得できます。

また、このAPIはSanctumの認証機能により、ログイン中にしか叩けない状態となっています。

Sanctumはログイン成功時にセッションIDを生成してくれるのですが、そのセッションIDからログイン状態を識別し、認証を行ってくれます。

なのでログアウト中にこのAPIを叩いてもユーザー情報は返ってこず、フロント側でもstateにユーザー情報が入らないので、ログイン状態にもならないというわけです。

詳しい仕組みは公式ドキュメントをご参照ください。


React(Redux)側の実装

次にReact側の実装です。

初回レンダリング時にLaravelで作ったAPIを叩く処理を実装します。

今回Reduxを使っているので、ログイン状態のstateはstoreで管理するとして、Redux Tool KitのcreateAsyncThunkを使ってAPIを叩く関数を作ります。

action.payloadでAPIの返り値(ユーザー情報)を受け取り、stateに入れます。

コードは以下の通りです。(実際はログイン、ログアウト処理もこのAuthSlice.tsに記述していますが、今回は省略します)

// AuthSlice.ts

import { AuthUserType } from "../../types/authType";
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import axios from "axios";
import { RootState } from "../../app/store";

// stateの初期値
const initialState: AuthUserType = {
    user: undefined,
    isLoading: false,
    error: undefined,
};

// ログイン中のユーザー情報を取得するAPIを叩く関数
export const fetchAuthUser = createAsyncThunk(
    "auth/fetchAuthUser",
    async () => {
        const response = await axios.get(`/api/user`);
        return response.data;
    }
);
export const authSlice = createSlice({
    name: "auth",
    initialState,
    reducers: {},
    extraReducers: (builder) => {
        builder
            .addCase(fetchAuthUser.pending, (state) => {
                state.isLoading = true;
                state.error = undefined;
            })
            .addCase(fetchAuthUser.fulfilled, (state, action) => {
                state.isLoading = false;
                state.user = action.payload; // fetchAuthUserが実行され、返り値がstateに入る
                state.error = undefined;
            })
            .addCase(fetchAuthUser.rejected, (state, action) => {
                state.isLoading = false;
                state.error = action.error.message;
            });
    },
});

export const selectAuth = (state: RootState) => state.auth;
export default authSlice.reducer;

fetchAuthUser をuseEffectで初回レンダリング時にdispatchします。

// App.tsx
const dispatch = useAppDispatch();
useEffect(() => {
    dispatch(fetchAuthUser());
}, []);

これで実装は完了です。

終わりに

React(Redux) × Laravelという少し特殊な環境のSPAでログイン状態を保持させる方法を紹介しました。

実装自体はとても簡単なのでぜひ参考にしていただければと思います。


ロジカルスタジオではPHPエンジニアを募集しています。

今回使用したLaravelは特によく使われる技術なので、ご興味のある方は是非以下よりご応募ください!

PHPエンジニア
即戦力募集中!PHPで世界をちょっとよくしたいエンジニアをWanted!
ロジカルスタジオは、テクノロジーとデザインの視点からクライアントの課題解決をめざす、大阪のクリエイティブプロダクションです。 クライアントの期待を超えて「もっと良くなる、を見つける」のが私たちのスタイル。企画・提案からデザイン制作・システム構築、運用、改善提案をワンストップで行えるのが一番の強みです。近年ではその実績と品質が評価され、案件も急増しています。 代表の古川が掲げる企業理念は「絆を大切に、周りの人を豊かにし、社会に貢献する」。 私たちはこのミッションを推進するため、「新しい技術へのチャレンジ精神」を軸に、「切磋琢磨する仲間」と「働きやすい職場環境」を整え、「成長と可能性を大切にする風土」を育ててきました。 2019年9月に増床し、外部向けのセミナーにも活用できるカンファレンスルームを拡充。スタッフによる公式ブログや、マスコットキャラクター「ロージー&カール」によるTwitterなど、情報発信も強化しています。 可能性の芽をすくい上げられるこの場所を、より大きくしていきたい。 私たちと一緒に、このビジョンを実現しませんか。
株式会社ロジカルスタジオ
Invitation from 株式会社ロジカルスタジオ
If this story triggered your interest, have a chat with the team?
株式会社ロジカルスタジオ's job postings
4 Likes
4 Likes

Weekly ranking

Show other rankings
Like 岩村 充基's Story
Let 岩村 充基's company know you're interested in their content