Category: Frontend

0

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

리엑트 블로그 만들기 15 - Post Card List 만들기 2 리엑트 블로그 만들기 14 - Post Card List 만들기 리엑트 블로그 만들기 13 - 라우트 리엑트 블로그 만들기 12 - Loading 만들기 리엑트 블로그 만들기 11 - 회원가입 리덕스 작업 리엑트 블로그 만들기 10 - 회원가입 2 리엑트 블로그 만들기 9 - 회원가입 리엑트 블로그 만들기 8 - 로그인 & 로그아웃 리엑트 블로그 만들기 7 - Login Modal 만들기 2 리엑트 블로그 만들기 6 - Login Modal 만들기 1 리엑트 블로그 만들기 5 - 리덕스 세팅하기 리엑트 블로그 만들기 4 - Navbar 작성하기 리엑트 블로그 만들기 3 - Header 작성하기 리엑트 블로그 만들기 2 - Footer 작성하기 리엑트 블로그 만들기 1 - 초기 setting 하기 리엑트 블로그 만들기 8 - 로그인 & 로그아웃//LOGINexport const LOGIN_REQUEST = "LOGIN_REQUEST";export const LOGIN_SUCCESS = "LOGIN_SUCCESS";export const LOGIN_FAILURE = "LOGIN_FAILURE";//LOGINexport const LOGOUT_REQUEST = "LOGOUT_REQUEST";export const LOGOUT_SUCCESS = "LOGOUT_SUCCESS";export const LOGOUT_FAILURE = "LOGOUT_FAILURE";// CLEAR ERRORexport 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;

0

리엑트 블로그 만들기 7 - Login Modal 만들기 2

리엑트 블로그 만들기 15 - Post Card List 만들기 2 리엑트 블로그 만들기 14 - Post Card List 만들기 리엑트 블로그 만들기 13 - 라우트 리엑트 블로그 만들기 12 - Loading 만들기 리엑트 블로그 만들기 11 - 회원가입 리덕스 작업 리엑트 블로그 만들기 10 - 회원가입 2 리엑트 블로그 만들기 9 - 회원가입 리엑트 블로그 만들기 8 - 로그인 & 로그아웃 리엑트 블로그 만들기 7 - Login Modal 만들기 2 리엑트 블로그 만들기 6 - Login Modal 만들기 1 리엑트 블로그 만들기 5 - 리덕스 세팅하기 리엑트 블로그 만들기 4 - Navbar 작성하기 리엑트 블로그 만들기 3 - Header 작성하기 리엑트 블로그 만들기 2 - Footer 작성하기 리엑트 블로그 만들기 1 - 초기 setting 하기 리엑트 블로그 만들기 7 - Login Modal 만들기 2import React, { useEffect, useState } from "react";import { useDispatch, useSelector } from "react-redux";import { NavLink } from "react-router-dom";import { Alert, Button, Form, FormGroup, Input, Label, Modal, ModalBody, ModalHeader,} from "reactstrap";import { CLEAR_ERROR_REQUEST, LOGIN_REQUEST } from "../../redux/types";const LoginModal = () => { const [modal, setModal] = useState(false); const [localMsg, setLocalMsg] = useState(""); const [form, setValues] = useState({ email: "", password: "", }); const dispatch = useDispatch(); const { errorMsg } = useSelector((state) => state.auth); useEffect(() => { try { setLocalMsg(errorMsg); } catch (e) { console.log(e); } }, [errorMsg]); const handleToggle = () => { dispatch({ type: CLEAR_ERROR_REQUEST, }); setModal(!modal); }; const onChange = (e) => { setValues({ ...form, [e.target.name]: e.target.value, }); }; const onSubmit = (e) => { e.preventDefault(); const { email, password } = form; const user = { email, password }; console.log(user); dispatch({ type: LOGIN_REQUEST, data: user, }); }; return ( <div> <NavLink onClick={handleToggle} href="#"> Login </NavLink> <Modal isOpen={modal} toggle={handleToggle}> <ModalHeader toggle={handleToggle}>Login</ModalHeader> <ModalBody> {localMsg ? <Alert color="danger">{localMsg}</Alert> : null} <Form> <FormGroup> <Label for="email">Email</Label> <Input type="email" name="email" id="email" placeholder="Email" onChange={onChange} /> <Label for="passowrd">Passowrd</Label> <Input type="passowrd" name="passowrd" id="passowrd" placeholder="Passowrd" onChange={onChange} /> <Button color="dark" style={{ marginTop: "2rem" }} block /> </FormGroup> </Form> </ModalBody> </Modal> </div> );};export default LoginModal;

0

리엑트 블로그 만들기 6 - Login Modal 만들기 1

리엑트 블로그 만들기 15 - Post Card List 만들기 2 리엑트 블로그 만들기 14 - Post Card List 만들기 리엑트 블로그 만들기 13 - 라우트 리엑트 블로그 만들기 12 - Loading 만들기 리엑트 블로그 만들기 11 - 회원가입 리덕스 작업 리엑트 블로그 만들기 10 - 회원가입 2 리엑트 블로그 만들기 9 - 회원가입 리엑트 블로그 만들기 8 - 로그인 & 로그아웃 리엑트 블로그 만들기 7 - Login Modal 만들기 2 리엑트 블로그 만들기 6 - Login Modal 만들기 1 리엑트 블로그 만들기 5 - 리덕스 세팅하기 리엑트 블로그 만들기 4 - Navbar 작성하기 리엑트 블로그 만들기 3 - Header 작성하기 리엑트 블로그 만들기 2 - Footer 작성하기 리엑트 블로그 만들기 1 - 초기 setting 하기 리엑트 블로그 만들기 6 - Login Modal 만들기 1import { all, put } from "@redux-saga/core/effects";import axios from "axios";import { takeEvery } from "redux-saga";import { call, fork } from "redux-saga/effects";import { LOGIN_FAILURE, LOGIN_REQUEST, LOGIN_SUCCESS } 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({ ytpe: LOGIN_SUCCESS, payload: result.data, }); } catch (e) { yield put({ type: LOGIN_FAILURE, payload: e.response, }); }}function* watchLoginUser() { yield takeEvery(LOGIN_REQUEST, loginUser);}export default function* authSaga(){ yield all([ fork(watchLoginUser) ])}

0

리엑트 블로그 만들기 5 - 리덕스 세팅하기

리엑트 블로그 만들기 15 - Post Card List 만들기 2 리엑트 블로그 만들기 14 - Post Card List 만들기 리엑트 블로그 만들기 13 - 라우트 리엑트 블로그 만들기 12 - Loading 만들기 리엑트 블로그 만들기 11 - 회원가입 리덕스 작업 리엑트 블로그 만들기 10 - 회원가입 2 리엑트 블로그 만들기 9 - 회원가입 리엑트 블로그 만들기 8 - 로그인 & 로그아웃 리엑트 블로그 만들기 7 - Login Modal 만들기 2 리엑트 블로그 만들기 6 - Login Modal 만들기 1 리엑트 블로그 만들기 5 - 리덕스 세팅하기 리엑트 블로그 만들기 4 - Navbar 작성하기 리엑트 블로그 만들기 3 - Header 작성하기 리엑트 블로그 만들기 2 - Footer 작성하기 리엑트 블로그 만들기 1 - 초기 setting 하기 리엑트 블로그 만들기 5 - 리덕스 세팅하기//LOGINexport const LOGIN_REQUEST = "LOGIN_REQUEST";export const LOGIN_SUCCESS = "LOGIN_SUCCESS";export const LOGIN_FAILURE = "LOGIN_FAILURE";// CLEAR ERRORexport 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,} 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 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 LOGIN_FAILURE: localStorage.removeItem("token"); return { ...state, ...action.payload, token: null, user: null, userId: null, userRole: null, errorMsg: action.payload.data.msg, }; 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;

0

리엑트 블로그 만들기 4 - Navbar 작성하기

리엑트 블로그 만들기 15 - Post Card List 만들기 2 리엑트 블로그 만들기 14 - Post Card List 만들기 리엑트 블로그 만들기 13 - 라우트 리엑트 블로그 만들기 12 - Loading 만들기 리엑트 블로그 만들기 11 - 회원가입 리덕스 작업 리엑트 블로그 만들기 10 - 회원가입 2 리엑트 블로그 만들기 9 - 회원가입 리엑트 블로그 만들기 8 - 로그인 & 로그아웃 리엑트 블로그 만들기 7 - Login Modal 만들기 2 리엑트 블로그 만들기 6 - Login Modal 만들기 1 리엑트 블로그 만들기 5 - 리덕스 세팅하기 리엑트 블로그 만들기 4 - Navbar 작성하기 리엑트 블로그 만들기 3 - Header 작성하기 리엑트 블로그 만들기 2 - Footer 작성하기 리엑트 블로그 만들기 1 - 초기 setting 하기 리엑트 블로그 만들기 4 - Navbar 작성하기import React from "react";import { Link } from "react-router-dom";import { Collapse, Container, Nav, Navbar, NavbarToggler } from "reactstrap";const AppNavbar = () => { return ( <div> <Navbar color="dark" dark expand="lg" className="sticky-top"> <Container> <Link to="/" className="text-white text-decoration-none"> Victor의 블로그 </Link> <NavbarToggler /> <Collapse isOpen={true} navbar> <Nav className="ml-auto d-flex justify-content-around" navbar> {true ? ( <h1 className="text-white">authLink</h1> ) : ( <h1 className="text-white">gestLink</h1> )} </Nav> </Collapse> </Container> </Navbar> </div> );};export default AppNavbar; import React, { Fragment } from "react";import Header from "../components/Header";import Footer from "../components/Footer";import AppNavbar from "../components/AppNavbar";const MyRouter = () => ( <Fragment> <AppNavbar /> <Header> <h1>Hello Body</h1> </Header> <Footer></Footer> </Fragment>);export default MyRouter;

0

리엑트 블로그 만들기 3 - Header 작성하기

리엑트 블로그 만들기 15 - Post Card List 만들기 2 리엑트 블로그 만들기 14 - Post Card List 만들기 리엑트 블로그 만들기 13 - 라우트 리엑트 블로그 만들기 12 - Loading 만들기 리엑트 블로그 만들기 11 - 회원가입 리덕스 작업 리엑트 블로그 만들기 10 - 회원가입 2 리엑트 블로그 만들기 9 - 회원가입 리엑트 블로그 만들기 8 - 로그인 & 로그아웃 리엑트 블로그 만들기 7 - Login Modal 만들기 2 리엑트 블로그 만들기 6 - Login Modal 만들기 1 리엑트 블로그 만들기 5 - 리덕스 세팅하기 리엑트 블로그 만들기 4 - Navbar 작성하기 리엑트 블로그 만들기 3 - Header 작성하기 리엑트 블로그 만들기 2 - Footer 작성하기 리엑트 블로그 만들기 1 - 초기 setting 하기 리엑트 블로그 만들기 3 - Header 작성하기import React from "react";import { Row, Col } from "reactstrap";const Header = () => { return ( <div id="page-header"> <Row> <Col md="6" sm="auto" className="text-center m-auto"> <h1>Read Our Blog</h1> <p>Victor의 사이드 블로그 입니다.</p> </Col> </Row> </div> );};export default Header; #main-footer{ background: #343a40; color:#fff;}#page-header{ height:200px; background: url(./img/free-image.jpeg); background-position: 54% 94%; background-attachment: fixed; color: #fff; border-bottom: 1px #eee solid; padding-top: 60px;}

0

리엑트 블로그 만들기 2 - Footer 작성하기

리엑트 블로그 만들기 15 - Post Card List 만들기 2 리엑트 블로그 만들기 14 - Post Card List 만들기 리엑트 블로그 만들기 13 - 라우트 리엑트 블로그 만들기 12 - Loading 만들기 리엑트 블로그 만들기 11 - 회원가입 리덕스 작업 리엑트 블로그 만들기 10 - 회원가입 2 리엑트 블로그 만들기 9 - 회원가입 리엑트 블로그 만들기 8 - 로그인 & 로그아웃 리엑트 블로그 만들기 7 - Login Modal 만들기 2 리엑트 블로그 만들기 6 - Login Modal 만들기 1 리엑트 블로그 만들기 5 - 리덕스 세팅하기 리엑트 블로그 만들기 4 - Navbar 작성하기 리엑트 블로그 만들기 3 - Header 작성하기 리엑트 블로그 만들기 2 - Footer 작성하기 리엑트 블로그 만들기 1 - 초기 setting 하기 리엑트 블로그 만들기 2 - Footer 작성하기import React from "react";import { Row, Col } from "reactstrap";const Footer = () => { const thisYear = () => { const year = new Date().getFullYear(); return year; }; return ( <div id="main-footer" className="text-center m-center p-2"> <Row> <Col> <p> Copyright Copy <span>{thisYear()}</span> </p> </Col> </Row> </div> );};export default Footer; 패키지 설치 npm install node-sass sass-loaderyarn add node-sass sass-loader #main-footer{ background: #343a40; color:#fff;} import React from "react"import { Provider } from 'react-redux'import { ConnectedRouter } from 'connected-react-router'import store, { history } from "./store"import MyRouter from './routes/Router'import "bootstrap/dist/css/bootstrap.min.css";import "./assets/custom.scss"const App = () => { return ( <Provider store={store}> <ConnectedRouter history={history}> <MyRouter /> </ConnectedRouter> </Provider> );}export default App;

0

리엑트 블로그 만들기 1 - 초기 setting 하기

리엑트 블로그 만들기 15 - Post Card List 만들기 2 리엑트 블로그 만들기 14 - Post Card List 만들기 리엑트 블로그 만들기 13 - 라우트 리엑트 블로그 만들기 12 - Loading 만들기 리엑트 블로그 만들기 11 - 회원가입 리덕스 작업 리엑트 블로그 만들기 10 - 회원가입 2 리엑트 블로그 만들기 9 - 회원가입 리엑트 블로그 만들기 8 - 로그인 & 로그아웃 리엑트 블로그 만들기 7 - Login Modal 만들기 2 리엑트 블로그 만들기 6 - Login Modal 만들기 1 리엑트 블로그 만들기 5 - 리덕스 세팅하기 리엑트 블로그 만들기 4 - Navbar 작성하기 리엑트 블로그 만들기 3 - Header 작성하기 리엑트 블로그 만들기 2 - Footer 작성하기 리엑트 블로그 만들기 1 - 초기 setting 하기 리엑트 블로그 만들기 1 - 초기 setting 하기yarn add axios redux react-redux redux-saga react-router-dom connected-react-router dotenv bootstrap reactstrap Root Reducer 생성/src/redux/reducers/index.js import { connectRouter } from 'connected-react-router';import { combineReducers } from "redux";// Root Reducer를 생성한다.const createRootReducer = (history) => combineReducers({ router: connectRouter(history),});export default createRootReducer; Root Saga 생성/src/redux/sagas/index.js import { all } from 'redux-saga/effects';// Root Saga를 생성한다.export default function* rootSaga() { yield all([]);}