環境
- windows10
- DockerDesktop for Win 3.5.x
- Laravel 8.x
- PHP 8.x
- node v14.17.4
- npm 6.14.14
- React 17.0.1
- VsCode
- gitbash 2.32.0.1
事前準備
laravelにreactをインストールするとデフォルトだとapp.jsが起点になっているため、少し開発しづらいので、起点をindex.jsに変更する作業を行います。
コンパイル対象(元)のファイルを app.js -> index.jsに変更する
webpack.mix.js
mix.js("resources/js/index.js", "public/js")
.react()
// .sass('resources/sass/app.scss', 'public/css');
.postCss("resources/css/app.css", "public/css", [require("tailwindcss")]);
App.jsxを作成
import React from "react";
const App = () => {
return <p>App</p>;
};
export default App;
index.jsを作成
app.jsをコピーしてindex.jsを作成し、App.jsxを読み込ませます
require("./bootstrap");
import React from "react";
import ReactDOM from "react-dom";
import { Switch, Route, useHistory, BrowserRouter } from "react-router-dom";
import "../css/app.css";
import App from "./App";
import CalendarFrame from "./components/calendar/CalendarFrame";
if (document.getElementById("root")) {
ReactDOM.render(
<BrowserRouter>
<App />
<Switch>
<Route path="/calendar(/:date_id)?" component={CalendarFrame} />
</Switch>
</BrowserRouter>,
document.getElementById("root")
);
}
app.blade.phpを修正
ルートのidをappからrootに変更し、コンパイルされたjsファイルの読み込み先を js/app.jsからjs/index.jsに変更する
<script src="{{ asset('js/index.js') }}" defer></script>
〜省略〜
<body>
<div id="root">
</div>
</body>
ストアを構築する
redux関連のライブラリをinstall
npm i react-redux redux-thunk redux-devtools-extension
ディレクトリ準備
ストアの作成
/resources/js/reducks/store/initialState.js
export const initialState = {
users: {
email: "",
isSignedIn: false,
uid: "",
username: ""
}
};
/resources/js/reducks/store/store.js
import {
createStore as reduxCreateStore,
combineReducers,
} from "redux";
import thunk from "redux-thunk";
import { UsersReducer } from "../users/reducers";
export default function createStore(history) {
return reduxCreateStore(
combineReducers({
users: UsersReducer,
}),
);
}
actionsの作成
actionsはデータをreducersに渡すだけの役割
以下を作成(サインイン・アウト用のactionsを作成)
/resources/js/reducks/users/actions.js
export const SIGN_IN = "SIGN_IN";
export const signInAction = (userState) => {
return {
type: "SIGN_IN",
payload: userState
}
};
export const SIGN_OUT = "SIGN_OUT";
export const signOutAction = () => {
return {
type: "SIGN_OUT",
payload: null
}
};
reducersの作成
actionsから渡ってきたデータをもとにストアのstateを変更する役割
以下を作成(サインイン・アウト用のreducersを作成)
/resources/js/reducks/users/reducers.js
import * as Actions from "./actions";
import { initialState } from "../store/initialState";
export const UsersReducer = (state = initialState.users, action) => {
switch (action.type) {
case Actions.SIGN_IN:
return {
...state,
...action.payload,
};
case Actions.SIGN_OUT:
return {
...initialState.users,
};
default:
return state;
}
};
storeとreactアプリの接続
/resources/js/index.js
・ProviderとcreateStoreをimport
・読み込んだcreateStoreを実行
export const store = createStore();
・ProviederコンポーネントでReactアプリをラッピングしつつ、定義したstoreをpropsで渡す
<Provider store={store}>
</Provider>,
最終的なコード
require("./bootstrap");
import React from "react";
import ReactDOM from "react-dom";
import createStore from "./reducks/store/store";
import { Provider } from "react-redux";
import { Switch, Route, useHistory, BrowserRouter } from "react-router-dom";
import "../css/app.css";
import App from "./App";
import CalendarFrame from "./components/calendar/CalendarFrame";
export const store = createStore();
if (document.getElementById("root")) {
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<App />
<Switch>
<Route path="/calendar(/:date_id)?" component={CalendarFrame} />
</Switch>
</BrowserRouter>
</Provider>,
document.getElementById("root")
);
}
ボタンのクリックイベントに先ほど設定したsignInActionを実行するリスナーを設定する
import React from "react";
import { useDispatch, useSelector } from "react-redux";
import { signInAction } from "./reducks/users/actions";
const App = () => {
const dispatch = useDispatch();
const selector = useSelector((state) => state);
console.log(selector.users);
return (
<>
<button
className="border"
onClick={() =>
dispatch(
signInAction({
uid: "0001",
username: "テストマン",
isSignedIn: true,
})
)
}
>サインイン
</button>
</>
);
};
export default App;
ボタンをクリックして、コンソールにstoreのusersの情報が出力され、サインイン後の状態になっていればOK(isSinedinがtrue、uidとusernameに値が入る)
まとめ
いかがでしたでしょうか。本記事では、Laravel8・ReactのSPAに、ストア構築用のライブラリReduxを導入して認証の仕組みを構築する方法について紹介しています。