[노드, 리액트 기초 | React] #23. 로그인 페이지 구현

ppmyor·2022년 7월 25일
0

노드, 리액트 기초

목록 보기
23/26
post-thumbnail

드디어 로그인 페이지 구현 부분이다. redux 부분이 어려워서 여러번 복습해야할 것 같다.🥲 우선은 배운 부분을 정리해둔다!

강의에서는 진행하지 않았지만 보통은 Formik과 Yup 라이브러리를 통해서 유효성 체크하는 기능을 추가해준다고 한다. 나중에 한번 살펴보겠다!

🧐 로그인 페이지 구현

components/view/LoginPage/LoginPage.js

import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { loginUser } from "../../../_actions/user_action";
import { useNavigate } from "react-router-dom";

function LoginPage(props) {
  const dispatch = useDispatch();
  const navigate = useNavigate();

  const [Email, setEmail] = useState("");
  const [Password, setPassword] = useState("");

  const onEmailHandler = (event) => {
    setEmail(event.currentTarget.value);
  };

  const onPasswordHandler = (event) => {
    setPassword(event.currentTarget.value);
  };

  const onSubmitHandler = (event) => {
    event.preventDefault();

    let body = {
      email: Email,
      password: Password,
    };

    dispatch(loginUser(body)).then((response) => {
      if (response.payload.loginSuccess) {
        navigate(-1);
      } else {
        alert("Error");
      }
    });
  };

  return (
    <div
      style={{ display: "flex", justifyContent: "center", alignItems: "center", width: "100%", height: "100vh" }}
      onSubmit={onSubmitHandler}
    >
      <form style={{ display: "flex", flexDirection: "column" }}>
        <label>Email</label>
        <input type="email" value={Email} onChange={onEmailHandler} />
        <label>Password</label>
        <input type="password" value={Password} onChange={onPasswordHandler} />

        <br />
        <button>Login</button>
      </form>
    </div>
  );
}

export default LoginPage;
  1. form tag를 이용해서 로그인 할 때 정보들을 넣어줌
  • email
  • password
  • 확인 버튼
  1. 안에서 데이터를 변화시키려고 할 때는 state를 활용해서 변화를 시켜줌
  • email state 생성
  • password state 생성
    생성 후 state들을 각각 value에 넣어줌
  1. 타이핑 할 때 onChange event 를 발생시켜 state를 변화시킴 (state가 변화되면 value 또한 변화)
  • onEmailHandler function 생성
    - setEmail을 통해 event.currentTarget.value로 value를 바꾸어줌
  • onPasswordHandler funtion 생성
    - setPassword을 통해 event.currentTarget.value로 value를 바꾸어줌
  1. 로그인 button을 클릭했을 때 onSubmit event가 일어날 수 있게 form에 onSubmit Handler 추가
  • server에 보내고자 하는 값이 state가 갖고 있기 때문에 보내어줌
  • redux를 사용하기 때문에 dispatch를 통해 action인 user_action의 loginUser 으로 보내어줌
  1. loginSuccess가 true일 경우에는 landingPage로 넘겨줌
  • navigate를 이용

_actions/user_action.js

import axios from "axios";
import { LOGIN_USER } from "./types";

export function loginUser(dataToSubmit) {
  const request = axios.post("/api/users/login", dataToSubmit).then((response) => response.data);

  return {
    type: LOGIN_USER,
    payload: request,
  };
}

유저의 action들을 담아두려하는 파일이고, 해당 코드는 로그인을 시작 할 때의 action을 구현한 내용이다.

  1. loginUser function 생성

  2. axios를 통해 request 진행

  • 서버에서 받은 data를 request 변수에 저장
  1. return을 시켜 reducer로 보냄
  • action은 type과 response를 넣어주어야함
  • type 이름은 LOGIN_USER(type 파일에서 빼서 관리)
  • response(request)를 payload라는 변수명에 저장

_actions/types.js

export const LOGIN_USER = "login_user";

action의 type들만 빼서 관리해준다. 여러군데에서 사용하는데 요것이 오타가 날 수도 있고 이렇게 빼서 관리하는게 훨씬 깔끔하다.
유저 로그인과 관련한 type을 빼서 관리해준다!

_reducers/user_reducer.js

import { LOGIN_USER } from "../_actions/types";

const userReducer = (state = {}, action) => {
  switch (action.type) {
    case LOGIN_USER:
      return { ...state, loginSuccess: action.payload };

    default:
      return state;
  }
};

export default userReducer;

reducer는 previousState과 action을 조합해 nextState를 만든다.

  1. userReducer라는 function을 생성
  • parameter로 전 state과 action을 받음
  1. switch 문법 사용
  • action의 type들이 많아지는데 해당 type의 case별로 관리하기 위해 사용
  1. 다음 state를 return 시켜줌
  • state를 spread한 것에(예제에서는 빈 상태) loginSuccess에 해당 action의 payload를 넣어줌(node 서버의 값을 넣어줌)

_reducers/index.js

import { combineReducers } from "redux";
import user from "./user_reducer";

const rootReducer = combineReducers({
  user,
});

export default rootReducer;

rootReducer에 user_reducer를 추가해준다!

🥲 문제

dispatch(loginUser(body)).then(response => {
  if(response.payload.loginSuccess) {
    props.history.push("/")
  } else {
    alert("Error");
  }
})

해당 강의에서는 LoginPage.js 의 dispatch 부분에서 로그인 성공 시 LandingPage로 넘기는 부분에서 위와 같이 작성한다.

그러면 요런 에러가 짜잔~

uncaught (in promise) typeerror cannot read properties of undefined (reading 'push')

처음에는 버전 문제인가 싶어서 다른 방법으로 해결하는법을 찾아봤는데 지금 찾아보니 버전 문제는 아닌 것 같다.
[React] history.push()로 props 데이터 넘겨주기

왜 안되었는지 잘 모르겠지만 useNavigate를 이용해서 navigate로 라우팅을 시켜주어 해결했다!

 dispatch(loginUser(body)).then((response) => {
      if (response.payload.loginSuccess) {
        navigate(-1);
      } else {
        alert("Error");
      }
    });
  };

➕ 참고

따라하며 배우는 노드, 리액트 시리즈 - 기본 강의 를 공부하며 작성한 글입니다.

profile
유영하는 개발자

0개의 댓글