Frontend
// 사용자 정보 관리 모듈
import { createAction, handleActions } from "redux-actions";
// 불변성 관리 패키지
import { produce } from "immer";
// axios
import axios from 'axios';
// Actions
const LOG_OUT = "LOG_OUT";
const SET_USER = 'SET_USER';
// Action Creators
const setUser = createAction(SET_USER, (user) => ({ user }));
const logOut = createAction(LOG_OUT, (user) => ({ user }));
// Initial state
const initialState = {
username: null,
is_login: false,
}
// 회원 가입
const signupAPI = (id, pwd, pwd_check) => {
return function (dispatch, getState, { history }) {
const API = "<http://localhost:8000/api/signup>";
axios.post(API,
{
"username": id,
"password": pwd,
"passwordConfirm": pwd_check,
},
{
headers: {
'Content-Type': 'application/json',
}
})
.then((response) => {
window.alert('회원가입 되었습니다. 로그인해주세요.')
history.push('/login')
}).catch((error) => {
console.log(error);
window.alert(error);
})
}
}
// 로그인
const loginAPI = (id, pwd) => {
return function (dispatch, getState, { history }) {
const API = "<http://localhost:8000/api/login>";
axios.post(API,
{
"username": id,
"password": pwd,
},
{
headers: {
'Content-Type': 'application/json',
}
})
.then((response) => {
if (response.data.token) {
// 로컬스토리지 저장
localStorage.setItem("is_token", response.data.token);
localStorage.setItem("login_id", id);
dispatch(setUser({
username: id,
}))
window.alert('로그인되었습니다.');
history.push('/');
}
}).catch((error) => {
console.log(error);
window.alert(error);
})
}
}
// 로그아웃
// 로컬스토리지에서 토큰 지우기
const logoutStorage = () => {
return function (dispatch, getState, { history }) {
const id = getState().user.username; // eslint-disable-line no-unused-vars
localStorage.removeItem("is_token");
localStorage.removeItem("login_id");
dispatch(logOut());
window.alert('로그아웃 되었습니다.');
// 로그아웃 후 메인페이지로
history.replace('/');
// 리덕스 초기화를 위한 새로고침
window.location.reload();
}
}
// 로그인 체크
const logInCheckStorage = () => {
return function (dispatch, getState, { history }) {
// 토큰 가져오기
const token = localStorage.getItem('is_token');
const id = localStorage.getItem('login_id');
// 토큰이 없으면 재로그인 alert
// 있다면 유지
if (!token) {
return
} else {
dispatch(setUser({
username: id,
}))
}
};
};
// Reducers
export default handleActions(
{
[SET_USER]: (state, action) => produce(state, (draft) => {
draft.username = action.payload.user.username;
draft.is_login = true;
}),
[LOG_OUT]: (state, action) =>
produce(state, (draft) => {
draft.user = null;
draft.is_login = false;
}),
},
initialState
);
// Action Creators export
const actionCreators = {
signupAPI,
loginAPI,
logoutStorage,
logInCheckStorage,
};
export { actionCreators };
// Redux Store
import { createStore, combineReducers, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import { createBrowserHistory } from "history";
import { connectRouter } from "connected-react-router";
// Modules
import User from "./modules/user";
export const history = createBrowserHistory();
// export한 Reducer를 모으기
const rootReducer = combineReducers({
user: User,
router: connectRouter(history),
});
// 미들웨어 적용
// history 넣기
const middlewares = [thunk.withExtraArgument({ history: history })];
// 지금의 환경
const env = process.env.NODE_ENV;
// logger
if (env === "development") {
const { logger } = require("redux-logger");
middlewares.push(logger);
}
// Chrome Extension
// Redux devTools 설정
const composeEnhancers =
typeof window === "object" && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
// Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize...
})
: compose;
// 미들웨어 묶기
const enhancer = composeEnhancers(applyMiddleware(...middlewares));
// 미들웨어와 리듀서를 엮어 store 생성
let store = (initialStore) => createStore(rootReducer, enhancer);
export default store();
import React from "react";
import "../styles/login.scss";
// 모듈
import { useDispatch } from "react-redux";
import { actionCreators as userActions } from "../redux/modules/user";
const Login = (props) => {
const dispatch = useDispatch();
// 로그인 정보
const [id, setId] = React.useState("");
const [pwd, setPwd] = React.useState("");
const { history } = props;
// 로그인, API 호출
const login = () => {
if (id === "" || pwd === "") {
window.alert('아이디 혹은 비밀번호가 공란입니다.');
return;
}
dispatch(userActions.loginAPI(id, pwd));
}
return (
<React.Fragment>
<body className="login_body">
<div className="header_box">
<h1 className="ridi_logo"
onClick={() => { history.push('/') }}
>MOVEE</h1>
</div>
<div className="container">
<div className="form_box">
<div className="inner_form">
<input
className="login_input"
placeholder="아이디"
type="text"
// 아이디 입력
onChange={(e) => {
setId(e.target.value);
}}
></input>
<input
className="login_input"
placeholder="비밀번호"
type="password"
// 비밀번호 입력
onChange={(e) => {
setPwd(e.target.value);
}}
// 엔터키 로그인
onKeyPress={(e) => {
if (e.key === 'Enter') {
login();
}
}}
></input>
</div>
<button
className="login_button"
// 로그인
onClick={login}
>로그인</button>
<button className="signin_button"
onClick={() => {
history.push('/signup')
}}
>회원가입</button>
</div>
</div>
</body>
</React.Fragment>
);
};
export default Login;
import React from 'react';
// 라우터
import { Route} from 'react-router-dom';
import { ConnectedRouter } from 'connected-react-router';
import { history } from '../redux/configStore';
// 페이지
import Main from '../pages/Main';
import Login from '../pages/Login';
import Signup from '../pages/Signup';
import CommunityP from '../pages/CommunityP';
import MobeeP from '../pages/MobeeP';
// 부트스트랩
import 'bootstrap/dist/css/bootstrap.min.css';
import { Switch } from 'react-router-dom';
const App = (props) => {
return (
<React.Fragment>
<ConnectedRouter history={history}>
<Switch>
<Route path='/' exact component={Main} />
<Route path='/login' exact component={Login} />
<Route path='/signup' exact component={Signup} />
</Switch>
</ConnectedRouter>
</React.Fragment>
)
};
export default App;
댓글