ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Social Media 만들기 - 5) logout 기능 만들기 (Header)
    NODE.JS 2021. 7. 6. 12:39

     

    header를 만들고 그 안에 logout기능을 만들어보자. 

     

    component>Header.js를 만들어주고 App.js에 넣어준다. 

        <div className="main">
              {auth.token && <Header/>}

    여기서 로그인페이지로 가도 로그인 되어있다면 페이지 이동하도록 login.js를 수정해준다. 

    import { useDispatch, useSelector } from 'react-redux';
    import { Link , useHistory} from 'react-router-dom';
    
    
         const {auth} = useSelector(state => state);
         const history = useHistory();
    
         useEffect(() => {
            if(auth.token) history.push("/")
        }, [auth.token, history])

     

    이제 헤더파일을 작성해준다. 

    여기서 navbar는 bootstrap에서 복사하는데, 

    index.html의 부트스트랩을 맞춰준다. 

        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css">
        <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.min.js"></script>
        
        <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
        <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css" rel="stylesheet">

     

    header.js

    import React from 'react'
    import { useDispatch, useSelector } from 'react-redux';
    import {Link, useLocation} from 'react-router-dom';
    import { logout } from '../redux/actions/authActions';
    
    const Header = () => {
        const navLinks = [
            {label:'Home', icon:'home', path:'/'},
            {label:'Message', icon:'near_me', path:'/message'},
            {label:'Discover', icon:'explore', path:'/discover'},
            {label:'Notify', icon:'favorite', path:'/notify'},
        ]
    
        const {auth, theme} = useSelector(state => state)
        const dispatch = useDispatch()
    
        const {pathname} = useLocation()
    
        const isActive = (pn) =>{
            if(pn ===pathname){
                return 'active'
            }
        }
    
    
        return (
            <nav className="navbar navbar-expand-lg navbar-light bg-light justify-content-between align-middle">
                <Link  to="/">
                    <h1 className="navbar-brand text-uppercase p-0 m-0" >Social Network</h1></Link>
                <button className="navbar-toggler" type="button" data-toggle="collapse" 
                data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" 
                aria-expanded="false" aria-label="Toggle navigation">
                    <span className="navbar-toggler-icon"></span>
                </button>
    
                <div className="menu" >
                    <ul className="navbar-nav flex-row">
                        {
                            navLinks.map((link, index)=>(
                                <li className={`nav-item px-2 ${isActive(link.path)}`} key={index}>
                                    <Link className="nav-link" to={link.path}>
                                        <span className="material-icons">{link.icon}</span>
                                    </Link>
                                </li>
                            ))
                        }
    
                        <li className="nav-item dropdown" style={{opacity: 1}} >
                            <span className="nav-link dropdown-toggle" id="navbarDropdown" 
                            role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                <img src={auth.user.avatar} alt="avatar" className="avatar" style={{filter: `${theme ? 'invert(1)': 'invert(0)'}`}}/>
                            </span>
    
                            <div className="dropdown-menu" aria-labelledby="navbarDropdown">
    
                                <Link className="dropdown-item" to={`/profile/${auth.user_id}`}>Profile</Link>
                                <label className="dropdown-item" htmlFor="theme">{theme ? "Light mode":'Dark mode'}</label>
                                <div className="dropdown-divider"></div>
                                <Link className="dropdown-item" to="/" onClick={()=>dispatch(logout())}>Logout</Link>
                            </div>
                        </li>
                    </ul>
    
                </div>                  
            </nav>        
        )
    }
    
    export default Header

     

     

    index.css 에 디자인 추가

    img{
      object-fit: cover;
    }
    
    .avatar {
     width: 30px ;
     height: 30px ; 
     border-radius: 50% ;
     border: 2px solid black;
    }
    
    /* ------AUTH--------- */
    @import url("./styles/auth.css");
    
    /* ------LOADING--------- */
    @import url("./styles/loading.css");
    
    /* ------LOADING--------- */
    @import url("./styles/header.css");

     

     

     

     

    logout의 기능을 위해서 action을 설정해준다. 

    export const logout = () =>async (dispatch) =>{
    
        try{
            localStorage.removeItem('firstLogin')
    
            await postDataAPI('logout')
            window.location.href="/"
        } catch (err) {
            dispatch({ 
                type: GLOBALTYPES.ALERT, 
                payload: {
                    error: err.response.data.msg
                } 
            })
        }}

     

    추가로 theme의 속성을 사용하기 위해서 (mode 변경)

    globaltype을 추가해준다.

    export const GLOBALTYPES={
        AUTH:"AUTH",
        ALERT:"ALERT",
        THEME:"THEME"
    }

    themReducer를 생성하고 추가

    import {GLOBALTYPES} from '../actions/globalTypes';
    
    const initialState = false;
    
    const themeReducer = (state=initialState, action) =>{
        switch(action.type){
            case GLOBALTYPES.THEME:
                return action.payload;
            default :
                return state;
        }
    
    }
    
    export default themeReducer;

    index.js/reducer에 추가해준다.

    import { combineReducers } from "redux";
    import auth from './authReducers';
    import alert from './alertReducer';
    import theme from './themeReducer';
    
    export default combineReducers({
        auth,
        alert,
        theme
    })

     

     

    추가로 아이콘의 설정을 따로 꺼내서 정의해준다. 

    component>Avatar.js생성

    import React from 'react'
    import { useSelector } from 'react-redux'
    
    const Avatar = ({src}) => {
        const {theme} = useSelector(state => state)
        return (
            <img src={src} alt="avatar" className="avatar" style={{filter: `${theme ? 'invert(1)': 'invert(0)'}`}}/>
        )
    }
    
    export default Avatar

    header.js에 다음과 같이 변경해준다.

    import Avatar from '../components/Avatar';
    
                        <li className="nav-item dropdown" style={{opacity: 1}} >
                            <span className="nav-link dropdown-toggle" id="navbarDropdown" 
                            role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                <Avatar src={auth.user.avatar} />
                            </span>

    로그아웃도 잘 된다.

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

Designed by Tistory.