useAuth 커스텀 훅을 만들어서 로그인 상태 값을 받아온다.
이때 로그인 상태는 로컬 스토리지에 저장된 JWT Access Token의 생명주기와 동일하다.
import { useEffect, useState } from "react";
export function useAuth() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
useEffect(() => {
const token = localStorage.getItem("jwt");
if (token) {
// 토큰이 있으면 로그인 상태로 판단
setIsLoggedIn(true);
} else {
// 토큰이 없으면 로그아웃 상태로 판단
setIsLoggedIn(false);
}
}, []);
return {
isLoggedIn,
setIsLoggedIn,
};
}
제어할 페이지를 감쌀 Protected 컴포넌트 이다.
로그인 된 상태
에서option 이 false
로 지정된 Protected 컴포넌트로 감싼 페이지에 접근하면
/home
으로 리다이렉트한다.
로그인이 안된 상태
에서option이 true
로 지정된 Protected 컴포넌트로 감싼 페이지에 접근하면
/login
으로 리다이렉트한다.
import React from "react";
import { Navigate } from "react-router";
import { useAuth } from "../../hooks/useAuth";
interface ProtectedPageProps {
element: React.ReactNode;
option: boolean;
}
const Protected: React.FC<ProtectedPageProps> = ({
element,
option,
}: ProtectedPageProps) => {
const { isLoggedIn } = useAuth();
if (isLoggedIn && !option) {
return <Navigate to="/home" />;
}
if (!isLoggedIn && option) {
return <Navigate to="/login" />;
}
return element;
};
export default Protected;
기존 Route의 element에 Protected 로 감싼 컴포넌트를 넣어준다.
import { Route, Routes } from "react-router";
import Login from "./pages/Login/Login";
import SignUp from "./pages/SignUp/SignUp";
import FindPassword from "./pages/FindPassword/FindPassword";
import Home from "./pages/Home/Home";
import Story from "./pages/Story/Story";
import SearchTag from "./pages/SearchTag/SearchTag";
import Feed from "./pages/Feed/Feed";
import Profile from "./pages/Profile/Profile";
import EditProfile from "./pages/EditProfile/EditProfile";
import SavedProfile from "./pages/SavedProfile/SavedProfile";
import IconsTest from "./pages/IconsTest/IconsTest";
import SetPassword from "./pages/SetPassword/SetPassword";
import Protected from "./pages/Protected/Protected";
const LoginRoutes = [
{ path: "/home", component: <Home /> },
{ path: "/stories/:userName/:storyId", component: <Story /> },
{ path: "/explore/tags/:query", component: <SearchTag /> },
{ path: "/feed/:feedId", component: <Feed /> },
{ path: "/accounts/:userName", component: <Profile /> },
{ path: "/accounts/:userName/edit", component: <EditProfile /> },
{ path: "/accounts/:userName/feed/saved", component: <SavedProfile /> },
];
const LogoutRoutes = [
{ path: "/login", component: <Login /> },
{ path: "/signup", component: <SignUp /> },
{ path: "/help/password", component: <FindPassword /> },
{ path: "/help/newpassword", component: <SetPassword /> },
];
function App() {
return (
<Routes>
{LogoutRoutes.map(({ path, component }) => (
<Route
key={path}
path={path}
element={<Protected element={component} option={false} />}
/>
))}
{LoginRoutes.map(({ path, component }) => (
<Route
key={path}
path={path}
element={<Protected element={component} option={true} />}
/>
))}
<Route path="/icons-test" element={<IconsTest />} />
</Routes>
);
}
export default App;