Private Route 설정하기 (Context API)

Ava Kim·2022년 6월 13일
2

프로젝트 페이지는 아래와 같이 구성되어 있다.

이 중 Home과 Sign in 페이지를 제외한 나머지 Search, My list, My page는 로그인 후 이용 가능하므로 private route 설정이 필요하다.

이전에는 App.js에서 login status를 받아와서 하위 컴포넌트에 모두 prop 으로 전달하는 방식을 썼었는데, login status는 전역적으로 필요한 데이터이기 때문에 Context를 사용하고 Private route 컴포넌트를 따로 만들기로 했다.

Step 1. Auth_context 생성

//auth_context.js

import React from 'react';

export const AuthContext = React.createContext(null);

Step2. Auth_provider.js

Firebase Auth 관련한 로직을 모아 놓은 authService를 import 하고 onAuthChange로 받아온 userId 값과 authService를 AuthContext의 provider에 value 값으로 넘겨 준다.

//auth_provider.js

import React, { useEffect, useState } from 'react';
import { AuthContext } from '../context/auth_context';
import { firebaseApp } from '../service/firebase';
import AuthService from '../service/auth_service';

const authService = new AuthService(firebaseApp);

const AuthProvider = ({ children }) => {
  const [userId, setUserId] = useState(null);

  useEffect(() => {
    authService.onAuthChange((user) => {
      user ? setUserId(user.uid) : setUserId(null);
    });
  }, []);

  return (
    <AuthContext.Provider value={{ authService, userId }}>
      {children}
    </AuthContext.Provider>
  );
};

export default AuthProvider;

Step3. RequireAuth.js 생성

useContext를 이용해 userId를 받아오는데, 만약 userId가 없다면 login 페이지로 이동하는 컴포넌트를 생성한다.

// RequireAuth.js

import React, { useContext } from 'react';
import { useLocation, Navigate } from 'react-router-dom';
import { AuthContext } from '../../context/auth_context';

const RequireAuth = ({ children }) => {
  const { userId } = useContext(AuthContext);
  const location = useLocation();

  if (!userId) {
    return <Navigate to='/login' state={{ from: location }} replace />;
  }

  return children;
};

export default RequireAuth;

Step4. App.js

private 설정이 필요한 컴포넌트를 RequireAuth로 감싸주면 된다.

// app.js

...
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import RequireAuth from './component/Layout/RequireAuth';

const App = ({ cardRepo }) => {
  return (
    <Router>
      <Routes>
        <Route path='/' element={<Home />} />
        <Route path='/login' element={<SignUp />} />
        <Route
          path='/search'
          element={
            <RequireAuth>
              <Search cardRepo={cardRepo} />
            </RequireAuth>
          }
        />
        <Route
          path='/my-list'
          element={
            <RequireAuth>
              <MyList cardRepo={cardRepo} />
            </RequireAuth>
          }
        />
        <Route
          path='/my-page'
          element={
            <RequireAuth>
              <MyPage cardRepo={cardRepo} />
            </RequireAuth>
          }
        />
      </Routes>
    </Router>
  );
};
profile
FE developer | self-believer | philomath

0개의 댓글