React Router 4 の useContext フックとグローバルステートで認証を管理
React Router 4 で認証済みルートを実装するには、いくつかの方法があります。ここでは、最も一般的な 2 つの方法を紹介します。
useAuth カスタムフックを使用する
この方法は、useContext
フックを使用して、認証状態をコンポーネント間で共有することを前提としています。
手順:
useAuth
カスタムフックを作成します。このフックは、認証状態と、ログイン/ログアウトなどの認証関連の関数を提供します。- 各コンポーネントで
useAuth
フックを使用し、認証状態を取得します。 PrivateRoute
コンポーネントを作成します。このコンポーネントは、useAuth
フックを使用して、ユーザーが認証されているかどうかを確認します。認証されていない場合、ログインページにリダイレクトします。- 認証が必要なルートを
PrivateRoute
でラップします。
例:
// useAuth.js
import React, { useState, useContext } from 'react';
const AuthContext = React.createContext();
const useAuth = () => {
const [auth, setAuth] = useState(false);
const login = () => {
setAuth(true);
};
const logout = () => {
setAuth(false);
};
return { auth, login, logout };
};
export default useAuth;
// PrivateRoute.js
import React from 'react';
import { Redirect } from 'react-router-dom';
import useAuth from './useAuth';
const PrivateRoute = ({ component: Component, ...rest }) => {
const auth = useAuth();
if (!auth.auth) {
return <Redirect to='/login' />;
}
return <Component {...rest} />;
};
export default PrivateRoute;
// App.js
import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import PrivateRoute from './PrivateRoute';
import Home from './Home';
import Login from './Login';
const App = () => {
return (
<BrowserRouter>
<Routes>
<Route path='/login' element={<Login />} />
<PrivateRoute path='/' element={<Home />} />
</Routes>
</BrowserRouter>
);
};
export default App;
React Router 4 の useContext フックを使用する
この方法は、認証状態をグローバルステートを使用して管理することを前提としています。
- 認証状態をグローバルステートに保存します。
useContext
フックを使用して、各コンポーネントで認証状態を取得します。Route
コンポーネントのrender
プロップを使用して、認証されたユーザーのみがアクセスできるコンポーネントを条件レンダリングします。
// App.js
import React, { useState, createContext } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
const AuthContext = createContext();
const App = () => {
const [auth, setAuth] = useState(false);
const login = () => {
setAuth(true);
};
const logout = () => {
setAuth(false);
};
return (
<AuthContext.Provider value={{ auth, login, logout }}>
<BrowserRouter>
<Routes>
<Route path='/login' element={<Login />} />
<Route path='/' element={<Home />} render={(props) => (auth ? <Home {...props} /> : <Redirect to='/login' />)} />
</Routes>
</BrowserRouter>
</AuthContext.Provider>
);
};
export default App;
// Home.js
import React, { useContext } from 'react';
import AuthContext from './AuthContext';
const Home = () => {
const { auth } = useContext(AuthContext);
if (!auth) {
return null;
}
return (
<div>
<h1>Welcome Home!</h1>
</div>
);
};
export default Home;
これらの方法は、React Router 4 で認証済みルートを実装するための 2 つの一般的な方法です。どの方法を使用するかは、具体的なニーズと要件によって異なります。
React Router 4 で認証済みルートを実装するためのサンプルコード
以下のサンプルコードは、React Router 4 で認証済みルートを実装する方法を 2 つの異なる方法で示しています。
useAuth カスタムフックを使用する
// useAuth.js
import React, { useState, useContext } from 'react';
const AuthContext = React.createContext();
const useAuth = () => {
const [auth, setAuth] = useState(false);
const login = () => {
setAuth(true);
};
const logout = () => {
setAuth(false);
};
return { auth, login, logout };
};
export default useAuth;
// PrivateRoute.js
import React from 'react';
import { Redirect } from 'react-router-dom';
import useAuth from './useAuth';
const PrivateRoute = ({ component: Component, ...rest }) => {
const auth = useAuth();
if (!auth.auth) {
return <Redirect to='/login' />;
}
return <Component {...rest} />;
};
export default PrivateRoute;
// App.js
import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import PrivateRoute from './PrivateRoute';
import Home from './Home';
import Login from './Login';
const App = () => {
return (
<BrowserRouter>
<Routes>
<Route path='/login' element={<Login />} />
<PrivateRoute path='/' element={<Home />} />
</Routes>
</BrowserRouter>
);
};
export default App;
// Home.js
import React from 'react';
import { useContext } from 'react';
import AuthContext from './AuthContext';
const Home = () => {
const { auth } = useContext(AuthContext);
if (!auth) {
return null;
}
return (
<div>
<h1>Welcome Home!</h1>
</div>
);
};
export default Home;
// Login.js
import React from 'react';
import { useContext } from 'react';
import AuthContext from './AuthContext';
const Login = () => {
const { auth, login } = useContext(AuthContext);
const handleSubmit = (event) => {
event.preventDefault();
login();
};
return (
<div>
<h1>Login</h1>
<form onSubmit={handleSubmit}>
<label>
Username:
<input type='text' />
</label>
<label>
Password:
<input type='password' />
</label>
<button type='submit'>Login</button>
</form>
</div>
);
};
export default Login;
この例では、useAuth
カスタムフックを使用して、認証状態と、ログインとログアウトのための関数を提供します。各コンポーネントは useAuth
フックを使用して認証状態を取得し、PrivateRoute
コンポーネントを使用して認証が必要なルートを保護します。
React Router 4 の useContext フックを使用する
// App.js
import React, { useState, createContext } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
const AuthContext = createContext();
const App = () => {
const [auth, setAuth] = useState(false);
const login = () => {
setAuth(true);
};
const logout = () => {
setAuth(false);
};
return (
<AuthContext.Provider value={{ auth, login, logout }}>
<BrowserRouter>
<Routes>
<Route path='/login' element={<Login />} />
<Route path='/' element={<Home />} render={(props) => (auth ? <Home {...props} /> : <Redirect to='/login' />)} />
</Routes>
</BrowserRouter>
</AuthContext.Provider>
);
};
export default App;
// Home.js
import React, { useContext } from 'react';
import AuthContext from './AuthContext';
const Home = () => {
const { auth } = useContext(AuthContext);
if (!auth) {
return null;
}
React Router 4 で認証済みルートを実装するその他の方法
上記で紹介した 2 つの方法は、React Router 4 で認証済みルートを実装するための最も一般的な方法ですが、他にもいくつか方法があります。
React Router 6 には、useAuth
フックと useOutletContext
フックを組み合わせることで、認証済みルートを実装するための新しい方法が導入されました。この方法は、より簡潔で、コードの可読性も高くなります。
// App.js
import React, { useState } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { useAuth } from 'react-router-dom';
const App = () => {
const [auth, setAuth] = useState(false);
const login = () => {
setAuth(true);
};
const logout = () => {
setAuth(false);
};
return (
<BrowserRouter>
<Routes>
<Route path='/login' element={<Login />} />
<Route path='/' element={<Home />} render={(props) => (auth ? <Home {...props} /> : <Redirect to='/login' />)} />
</Routes>
</BrowserRouter>
);
};
export default App;
// Home.js
import React from 'react';
import { useAuth } from 'react-router-dom';
const Home = () => {
const auth = useAuth();
if (!auth) {
return null;
}
return (
<div>
<h1>Welcome Home!</h1>
</div>
);
};
export default Home;
// Login.js
import React from 'react';
import { useNavigate } from 'react-router-dom';
const Login = () => {
const navigate = useNavigate();
const handleSubmit = (event) => {
event.preventDefault();
// ログイン処理
navigate('/');
};
return (
<div>
<h1>Login</h1>
<form onSubmit={handleSubmit}>
<label>
Username:
<input type='text' />
</label>
<label>
Password:
<input type='password' />
</label>
<button type='submit'>Login</button>
</form>
</div>
);
};
export default Login;
カスタムロジックを使用する
独自のロジックを使用して、認証済みルートを実装することもできます。これは、より複雑な認証要件がある場合に役立ちます。
// App.js
import React, { useState } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
const App = () => {
const [auth, setAuth] = useState(false);
const isAuthenticated = () => {
// 認証ロジック
return true; // 例
};
const handleLogin = () => {
setAuth(true);
};
const handleLogout = () => {
setAuth(false);
};
return (
<BrowserRouter>
<Routes>
<Route path='/login' element={<Login onLogin={handleLogin} />} />
<Route path='/' element={<Home isAuthenticated={isAuthenticated} onLogout={handleLogout} />} />
</Routes>
</BrowserRouter>
);
};
export default App;
// Home.js
import React from 'react';
const Home = ({ isAuthenticated, onLogout }) => {
if (!isAuthenticated) {
return <Redirect to='/login' />;
}
return (
<div>
<h1>Welcome Home!</h1>
<button onClick={onLogout}>Logout</button>
</div>
);
};
export default Home;
// Login.js
import React from 'react';
const Login = ({ onLogin }) => {
const handleSubmit = (event) => {
event.preventDefault();
// ログイン処理
onLogin();
};
return (
<div>
<h1>Login</h1>
<form onSubmit={handleSubmit}>
<label>
Username:
<input type='text' />
</label>
<label>
Password:
<input type='password' />
</label>
<button type='submit'>Login</button>
javascript reactjs react-router