티스토리 뷰
🌱 [인프런] 따라하며 배우는 노드, 리액트 시리즈 - 기본강의
# 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 |
프론트엔드 개발자 삐롱히의 개발 & 공부 기록 블로그