SPAを制作しているときに、Reactの状態管理でログイン状態かログアウト状態かを取得したかったため、useReducertとuseContextで実装しました。
目次
方針
- ログイン状態を判断するstateをグローバルで管理する
- そのstateには、ログイン状態であればユーザーのidを挿入し、ログアウト状態であればnullを挿入する
Reducerを作成する(UserAuthReducer.ts)
Reducer用のファイルを作成し、下記コードを作成しました。
export type UserAuthState = {
id: string | null
};
export type UserAuthAction = {
type: 'setId'
payload: string
} | {
type: 'removeId'
};
export const userAuthReducer = (state: UserAuthState, action: UserAuthAction): UserAuthState => {
switch (action.type) {
case 'setId':
return {
...state,
id: action.payload
};
case 'removeId':
return {
...state,
id: null
};
default:
return {
state
};
}
}
export const initialState: UserAuthState = {id: null};
Contextを作成する(UserAuthContext.ts)
私はContext用のファイルを作成しましたが、親コンポーネントのファイルに直接書く方もいるようですので、自由です。
import React, { createContext } from 'react';
import { UserAuthState, UserAuthAction } from './reducers/UserAuthReducer';
export const UserAuthContext = createContext({} as {
state: UserAuthState;
dispatch: React.Dispatch<UserAuthAction>;
});
親コンポーネントにProviderを設置(app.tsx)
stateを適用したいコンポーネントたちをContext.Providerで囲みます。
// React
import React, { useReducer } from 'react';
import ReactDOM from 'react-dom';
// ContextProvider
import { UserAuthReducer, initialState } from './reducers/UserAuthReducer';
import { UserAuthContext } from './UserAuthContext';
// Components
import Search from './Search';
import Top from './Top';
import Login from './Login';
const App: React.FC = () => {
const [state, dispatch] = useReducer(UserAuthReducer, initialState)
return (
<UserAuthContext.Provider value={{ state, dispatch }}>
<div id="global-container">
<Login />
<Top />
<Search />
</div>
</UserAuthContext.Provider>
)
}
if (document.getElementById('app')) {
ReactDOM.render(<App />, document.getElementById('app'));
}
ログイン時にstateを更新する処理を作成(Login.tsx)
以下をログイン成功時の処理と一緒に行えばOK。
import React from 'react';
import { UserAuthContext } from './UserAuthContext';
export const Login: React.FC = () => {
const { dispatch } = React.useContext(UserAuthContext)
// API等を実行し、user idを取得
dispatch({
type: 'setId',
payload: res.data.user.id,
});
// ...
return (
<div>
{/* ... */}
</div>
)
}
ログアウト時はこんな感じ。
import React from 'react';
import { UserAuthContext } from './UserAuthContext';
export const Login: React.FC = () => {
const { state, dispatch } = React.useContext(UserAuthContext)
const logout = {
console.log(`ログアウト: ${state.id}`) // stateの値もこうやって取れる
dispatch({
type: 'removeId'
});
// その他処理
}
return (
<div>
{/* ... */}
</div>
)
}
以上です。少しでも参考になれば幸いです。