리엑트 블로그 만들기 8 - 로그인 & 로그아웃

리엑트 블로그 만들기 8 - 로그인 & 로그아웃

//LOGIN
export const LOGIN_REQUEST = "LOGIN_REQUEST";
export const LOGIN_SUCCESS = "LOGIN_SUCCESS";
export const LOGIN_FAILURE = "LOGIN_FAILURE";

//LOGIN
export const LOGOUT_REQUEST = "LOGOUT_REQUEST";
export const LOGOUT_SUCCESS = "LOGOUT_SUCCESS";
export const LOGOUT_FAILURE = "LOGOUT_FAILURE";

// CLEAR ERROR
export const CLEAR_ERROR_REQUEST = "CLEAR_REQUEST";
export const CLEAR_ERROR_SUCCESS = "CLEAR_SUCCESS";
export const CLEAR_ERROR_FAILURE = "CLEAR_FAILURE";
import {
LOGIN_REQUEST,
LOGIN_SUCCESS,
LOGIN_FAILURE,
CLEAR_ERROR_REQUEST,
CLEAR_ERROR_SUCCESS,
CLEAR_ERROR_FAILURE,
LOGOUT_REQUEST,
LOGOUT_SUCCESS,
LOGOUT_FAILURE,
} from "../types";

const initialState = {
token: localStorage.getItem("token"),
isAuthenticated: null,
isLoading: false,
user: "",
userId: "",
userName: "",
userRole: "",
errorMsg: "",
successMsg: "",
};

const authReducer = (state = initialState, action) => {
switch (action.type) {
case LOGOUT_REQUEST:
case LOGIN_REQUEST:
return {
...state,
errorMsg: "",
};
case LOGIN_SUCCESS:
localStorage.setItem("token", action.payload.token);
return {
...state,
...action.payload,
isAuthenticated: true,
isLoading: false,
userId: action.payload.user.id,
userRole: action.payload.user.role,
errorMsg: "",
};
case LOGOUT_FAILURE:
case LOGIN_FAILURE:
localStorage.removeItem("token");
return {
...state,
...action.payload,
token: null,
user: null,
userId: null,
userRole: null,
errorMsg: action.payload.data.msg,
};
case LOGOUT_SUCCESS:
localStorage.removeItem("token");
return {
...state,
...action.payload,
token: null,
user: null,
userId: null,
isAuthenticated: false,
isLoading: false,
userRole: null,
errorMsg: "",
};
case CLEAR_ERROR_REQUEST:
return {
...state,
errorMsg: null,
};
case CLEAR_ERROR_SUCCESS:
return {
...state,
errorMsg: null,
};
case CLEAR_ERROR_FAILURE:
return {
...state,
errorMsg: null,
};
default:
return state;
}
};

export default authReducer;
import { all, put } from "@redux-saga/core/effects";
import axios from "axios";
import { call, fork, takeEvery } from "redux-saga/effects";
import {
LOGIN_FAILURE,
LOGIN_REQUEST,
LOGIN_SUCCESS,
LOGOUT_REQUEST,
} from "../types";

const loginUserAPI = (loginData) => {
console.log(loginData, "loginData");
const config = {
headers: {
"Content-Type": "application/json",
},
};

return axios.post("api/auth", loginData, config);
};

function* loginUser(action) {
try {
const result = yield call(loginUserAPI, action.payload);
console.log(result);
yield put({
type: LOGIN_SUCCESS,
payload: result.data,
});
} catch (e) {
yield put({
type: LOGIN_FAILURE,
payload: e.response,
});
}
}

function* logout(action) {
try {
const result = yield call(loginUserAPI, action.payload);
console.log(result);
yield put({
type: LOGIN_SUCCESS,
});
} catch (e) {
yield put({
type: LOGIN_FAILURE,
});
console.log(e);
}
}

function* watchLoginUser() {
yield takeEvery(LOGIN_REQUEST, loginUser);
}

function* watchLogout() {
yield takeEvery(LOGOUT_REQUEST, logout);
}

export default function* authSaga() {
yield all([fork(watchLoginUser), fork(watchLogout)]);
}
import React, { useCallback, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Link } from "react-router-dom";
import { Collapse, Container, Nav, Navbar, NavbarToggler } from "reactstrap";
import { LOGOUT_REQUEST } from "../redux/types";
import LoginModal from "./auth/LoginModal";

const AppNavbar = () => {
const [isOpen, setIsOpen] = useState(false);
const { isAuthenticated, user, userRole } = useSelector(
(state) => state.auth
);
console.log(userRole, "UserRole");

const dispatch = useDispatch();

const onLogout = useCallback(() => {
dispatch({
type: LOGOUT_REQUEST,
});
}, [dispatch]);

useEffect(() => {
setIsOpen(false);
}, [user]);

const handleToggle = () => {
setIsOpen(!isOpen);
};

return (
<div>
<Navbar color="dark" dark expand="lg" className="sticky-top">
<Container>
<Link to="/" className="text-white text-decoration-none">
Victor의 블로그
</Link>
<NavbarToggler onClick={handleToggle} />
<Collapse isOpen={isOpen} navbar>
<Nav className="ml-auto d-flex justify-content-around" navbar>
{isAuthenticated ? (
<h1 className="text-white">authLink</h1>
) : (
<LoginModal />
)}
</Nav>
</Collapse>
</Container>
</Navbar>
</div>
);
};

export default AppNavbar;
Share