[React] 로그인 상태 기반 페이지 리다이렉트

Narcoker·2023년 8월 7일
1

React

목록 보기
25/32
post-custom-banner

useAuth.tsx

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.tsx

제어할 페이지를 감쌀 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;

App.tsx

기존 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;
profile
열정, 끈기, 집념의 Frontend Developer
post-custom-banner

0개의 댓글