본문 바로가기
프레임워크/React.js

[React] Spring Boot, React, Redux 회원가입 구현 (프론트)

by Yikanghee 2022. 4. 27.
  • Frontend
    • redux
    // 사용자 정보 관리 모듈
    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 };
    
    • middleware 설정
    // 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;
    
    • app.js
    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;
    

'프레임워크 > React.js' 카테고리의 다른 글

[React] React 라우팅 처리  (0) 2022.04.16
[React] React 화면 전환  (0) 2022.04.15
[React] Redux 란?  (0) 2022.04.15
[React] axios 로그인 로그아웃  (0) 2022.04.14
[React] 배열을 사용한 일기 데이터 추가, 삭제  (0) 2022.04.11

댓글