ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [react] HOC를 사용한 페이지별 접근인증
    개발자의 공부는 은퇴까지 필수다/node js & react 2020. 11. 16. 11:42

    * HOC(higher-order component)

    > 특징 : 다른 컴포넌트를 받아 새로운 컴포넌트를 return하는 function

    > Auth라는 컴포넌트(HOC) 내에 다른 컴포넌트들을 삽입 가능

    const EnhancedComponent = higherOrderComponent ( WrapperdComponent );

     

    * HOC 적용방법

    1. front 폴더 아래 hoc 폴더 auth.js 생성

    import react, {useEffect} from 'react';
    import Axios from "axios";
    import {useDispatch} from "react-redux";
    import { auth } from '../_actions/user_action';
    
    /**
     *
     * @param specificComponent - 감쌀 컴포넌트
     * @param option            - null: 아무나 출인이 가능한 페이지, true: 로그인한 유저만 출입가능, false: 로그인한 유저는 접속불가능항 페이지
     * @param adminRoute        - 관리자만 접속할 수 있도록 하는 옵션
     * @returns {*}
     */
    export default function( SpecificComponent, option, adminRoute = null ) {
    
        function AuthenticationCheck( props ) {
    
            const dispatch = useDispatch();
    
            useEffect( () => {
    
    
                dispatch( auth() ).then( response => {
                   if( !response.payload.isAuth ) {
                       if( option ) {
                           props.history.push( '/login' )
                       }
                   }
                   else {
                        if( adminRoute && !response.payload.isAdmin ) {
                            props.history.push( '/' )
                        }
                        else {
                            props.history.push( '/' )
                        }
                   }
                } )
    
                //Axios.get( "/api/users/auth")
            }, [] )
    
            return (
                <SpecificComponent/>
    
            )
        }
    
        return AuthenticationCheck
    }

    2. action에 auth 추가 (파일명 user_action.js)

    //get 메소드는 body 부분이 필요하지 않음
    export function auth() {
    
        const request = axios.get('/api/user/auth' )
            .then( response => response.data )
    
        //  return을 시켜 Reducer로 보내줌.
        return {
            type: AUTH_USER,
            payload: request
        }
    }
    

    3. action에서 호출할 user_reducer 추가

    export default function( state = {}, action ) {
    
        //  정의 된 타입이 많아질 것이기 때문에 switch문을 사용
        switch( action.type ) {
            case LOGIN_USER :
                return {...state, loginSuccess: action.payload }
                break;
            case REGISTER_USER :
                return {...state, register: action.payload }
                break;
            case AUTH_USER :
                return {...state, userData: action.payload }
                break;
            default:
                return state;
        }
    }

     

    4. App.js 에 생성한 auth import 한 후 컴포넌트들을 Auth 로 감싸준다.

    import React from "react";
    import {
      BrowserRouter as Router,
      Switch,
      Route,
      Link
    } from "react-router-dom";
    
    import LandingPage from "./components/views/LandingPage/LandingPage";
    import LoginPage from "./components/views/LoginPage/LoginPage";
    import RegisterPage from "./components/views/RegisterPage/RegisterPage";
    import Auth from './hoc/auth';
    
    function App() {
      return (
          <Router>
            <div>
    
              <hr />
    
              {/*
              A <Switch> looks through all its children <Route>
              elements and renders the first one whose path
              matches the current URL. Use a <Switch> any time
              you have multiple routes, but you want only one
              of them to render at a time
            */}
              <Switch>
                <Route exact path="/" component={Auth( LandingPage, null, true)}/>
                <Route exact path="/login" component={Auth(LoginPage, false)}/>
                <Route exact path="/register" component={Auth(RegisterPage, false)}/>
              </Switch>
            </div>
          </Router>
      );
    }
    
    export default App;
    
    
    

     

    * props.history.push( "페이지url" )

    가리키는 페이지로 넘어가게 하기 위해서 props.history.push 해당 이벤트를 사용하는데

    이것을 사용하려면 필요한 라이브러리가 있다.

    import {withRouter} from 'react-router-dom';

    여기서 withRouter는 주로 history에 접근하여 컴포넌트에서 라우터를 조작하는 데 사용

    해당 라이브러리를 사용하지 않으면 아래와 같은 에러가 발생한다.

    LoginPage.js:36 Uncaught (in promise) TypeError: Cannot read property 'push' of undefined

     

     

     

     

     

    ==========================================

    ※추가정보

    해당 코드에서 세미콜론을 붙이고 안붙이고의 차이는 딱히 없다. 웬만하면 끝에 세미콜론을 붙여주는 것 추천

Designed by Tistory.