티스토리 뷰

📚 스터디 인증!

[8/4] 1차 스터디 11일차

2022. 8. 4. 20:35

🌱  [인프런] 따라하며 배우는 노드, 리액트 시리즈 - 기본강의 

 

 

[무료] 따라하며 배우는 노드, 리액트 시리즈 - 기본 강의 - 인프런 | 강의

이 강의를 통해서 리액트와 노드를 어떻게 사용하는지 기본적인 내용들을 배울 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com

 

 

 # boiler-plate 만들기 (#30 ~ #31)

 

 

30. Login 페이지 만들기 (2)

 

저번에 onEmailHandler, onPassswordHandler 만들어서 각 input 태그에서 문자가 입력되는 것까지 확인.

 

Login 버튼 클릭하여 form이 submit될 때 실행될 onSubmitHandler 작성해서 form 태그에 onSubmit 이벤트 달아줌

 

submit 시, 새로고침 막고  →   event.preventDefault()

Email과 Password state를 body에 저장한 다음

 

redux를 안쓴다면  Axios.post('/api/users/login', body).then(response => {response.body}) 으로 데이터를 넘겨주는데 

우리는 redux를 쓰니까 user_action 파일을 만들어서 사용

 

React Component   ---dispatch(action)--->  Action  --->  Reducer   --->  Store  --->   React Component  ]

// client/conponents/views/LoginPage/LoginPage.js

import React, { useState } from 'react'
import { useDispatch } from 'react-redux';
import { loginUser } from '../../../_actions/user_action';	// 다음 단계에서 만들 파일임

function LoginPage() {
  const dispatch = useDispatch();

  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))
  }


  return (
    <div style={{
      display: 'flex', justifyContent: 'center', alignItems: 'center', width: '100%', height: '100vh'
    }}>
      <form style={{display: 'flex', flexDirection: 'column'}} 
        onSubmit={onSubmitHandler}
      >
        <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

 

 

 

_actions 디렉터리에 user_action.js 파일 작성

type들만 따로 관리하기 위해 같은 디렉터리에 types.js 도 생성

 

[  React Component   ---dispatch(action)--->  Action  --->  Reducer   --->  Store  --->   React Component  ]

// client/src/_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)  // 서버에서 받은 데이터를 request에 저장
      .then(response => response.data);

    return {	// action은 { type, response } 으로 된 객체
      type: LOGIN_USER,
      payload: request    
    }   
}
// client/src/_actions/types.js

export const LOGIN_USER = "LOGIN_USER"

 

 

 

_reducers 디렉터리에 user_reducer.js 작성 후

rootReducer ( _reducers/index.js 파일에서 )  이전에 해놓은 주석 해제

 

 

[  React Component   ---dispatch(action)--->  Action  --->  Reducer   --->  Store  --->   React Component  ]

// client/src/_reducers/user_reducers.js

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

export default function(state = {}, action) { 
  switch (action.type) {   // user_action에서 넘겨준 action들을 type에 따라 실행할 일을 정해주기
    case LOGIN_USER:
      return {...state, loginSuccess: action.payload}   // reducer는 previousState와 action을 받아 next state을 리턴
      break;
    
    default:
      return state;
  }
}
// client/src/_reducers/index.js

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

const rootReducer = combineReducers({
  user,
});

export default rootReducer;

 

 

 

프로젝트 실행 후 크롬에서 Redux Dev Tools 실행해보면 State에 user: {} 가 생김

 

 

 

 

mongoDB에 저장되어있는 이메일과 비밀번호 입력 후 로그인 하면 loginSuccess: true 나옴

userId 도 redux store안에 들어와 있음

→  우리가 서버에서 로그인 성공 시 { loginSuccess: true, userId: user._id } 를 보내라고 했기 때문 (server/index.js)

 

3번째줄 loginSuccess는 user_reducer에서 쓴 loginSuccess

4-5번째줄 내용은 action.payload  =  axios.post('/api/users/login', dataTosubmit).then(response => response.data=  백엔드에서 가져온 모든 데이터(server/index.js에서 res.json()한 내용)

 

 

 

 

 

로그인 완료 후 랜딩페이지로 이동하기 위해 LoginPage.js에 useNavigate 모듈 추가 후 dispath().then 작성

( ! 강의에서는 props.history.push('/') 를 사용하나 React Router 버전이 업데이트(v5 → v6) 되면서 useHistory 대신 useNavigate를 사용해야함)

// client/src/_actions/user_action.js

...
import { useNavigate } from 'react-router-dom';

function LoginPage() {
  const navigate = useNavigate();

  ...

  const onSubmitHandler = (event) => {
   
    ...
   
    dispatch(loginUser(body))
      .then(response => {
        if(response.payload.loginSuccess) {
          navigate('/');
        }
      })
  }

...

 

 

 

 

 

31. 회원가입 페이지 만들기

 

로그인과 동일하게 component, action, reducer 작성

 

RegisterPage.js 작성

// components/views/RegisterPage/RegisterPage.js

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


function RegisterPage() {

  const navigate = useNavigate();
  const dispatch = useDispatch();

  const [Email, setEmail] = useState("");
  const [Name, setName] = useState("");
  const [Password, setPassword] = useState("");
  const [ConfirmPassword, setConfirmPassword] = useState("");

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

  const onNameHandler = (event) => {
    setName(event.currentTarget.value);
  }

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

  const onConfirmPasswordHandler = (event) => {
    setConfirmPassword(event.currentTarget.value);
  }

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

    if(Password !== ConfirmPassword) {
      return alert('비밀번호가 일치하지 않습니다.');
    }

    let body = {
      email: Email,
      name: Name,
      password: Password
    }

    dispatch(registerUser(body))
      .then(response => {
        if(response.payload.success) {
          navigate('/login');
        } else {
          alert("회원가입에 실패했습니다.");
        }
      })
    }
  
    
  return (
    <div style={{
      display: 'flex', justifyContent: 'center', alignItems: 'center', width: '100%', height: '100vh'
    }}>
      <form style={{display: 'flex', flexDirection: 'column'}} 
        onSubmit={onSubmitHandler}
      >
        <label>Email</label>
        <input type="email" value={Email} onChange={onEmailHandler} />
        <label>Name</label>
        <input type="text" value={Name} onChange={onNameHandler} />
        <label>Password</label>
        <input type="password" value={Password} onChange={onPasswordHandler} />
        <label>Confirm Password</label>
        <input type="password" value={ConfirmPassword} onChange={onConfirmPasswordHandler} />
        <br />
        <button>회원가입</button>
      </form>
    </div>
  )
}

export default RegisterPage

 

 

user_action.js 작성  /  types.js 작성

// _actions/type.js

export const LOGIN_USER = "LOGIN_USER"
export const REGISTER_USER = "REGISTER_USER"
// _actions/user_action.js

import axios from 'axios';
import {
  LOGIN_USER,
  REGISTER_USER
} from './types';

...

...

export function registerUser(dataTosubmit) { 

  const request = axios.post('/api/users/register', dataTosubmit)
    .then(response => response.data);

  return {
    type: REGISTER_USER,
    payload: request    
  }
}

 

 

user_reducer.js 작성

// _reducers/user_reducer.js

import {
  LOGIN_USER,
  REGISTER_USER
} from '../_actions/types';


export default function(state = {}, action) { 
  switch (action.type) {
    case LOGIN_USER:
      return {...state, loginSuccess: action.payload}
      break;
      
    case REGISTER_USER:
      return {...state, register: action.payload}
      break;
    
    default:
      return state;
  }
}

 

 

 

회원가입 폼 입력 후 회원가입 버튼 누르면 로그인페이지로 이동함

Redux Dev Tools 보면 정상적으로 register: { success: true } 뜸

 

 

 

반응형

'📚 스터디 인증!' 카테고리의 다른 글

[8/9] 1차 스터디 13일차  (0) 2022.08.09
[8/6] 1차 스터디 12일차  (0) 2022.08.07
[8/2] 1차 스터디 10일차  (0) 2022.08.02
[7/30] 1차 스터디 9일차  (0) 2022.07.30
[7/28] 1차 스터디 8일차  (0) 2022.07.28
프로필사진
개발자 삐롱히

프론트엔드 개발자 삐롱히의 개발 & 공부 기록 블로그