NODE.JS
MERN 기본파일 만들기 - 13)Register Page 만들기
dodop
2021. 5. 13. 15:14
Login페이지와 마찬가지로
회원을 등록하는 페이지도 만들 것이다.
App.js
import React from 'react';
import {Route, Switch} from "react-router-dom";
import About from "./about"//index.js가 기본이기 때문에 굳이 타이핑하지 않아도 된다.
import Login from "./RegisterLogin";
import Register from "./RegisterLogin/register";
function App() {
return (
<div >
<Switch>
{/* <Route path="/" component={Home} /> */}
<Route path = "/about" component={About}/>
<Route path = "/login" component={Login}/>
<Route path = "/register" component={Register}/>
</Switch>
</div>
);
}
export default App;
src>components>RegisterLogin>register.js
index.js에서와 비슷하게 lastname, name, email, password, password Comfirmation파트를 만들어준다.
isFormValid에 모든 폼이 다 작성해야만 다음으로 넘어가고, 비밀번호가 잘 작성되었는지 확인하는 파트를 넣어준다.
passwordValid는 비밀번호가 6자 이상인지 확인하고 비밀번호와 비밀번호 확인이 일치하는지 확인한다.
isFormEmpty는 비어있는 칸이 하나라도 있는지 확인한다.
import React, { Component } from 'react'
import {connect} from 'react-redux';
import {registerUser} from '../../actions/user_actions';
class Register extends Component {
state = {
lastname: "",
name:"",
email:"",
password: "",
passwordConfirmation:"",
errors:[]
};
handleChange = event =>{
this.setState({[event.target.name]: event.target.value})
}
displayErrors = errors=>{
errors.map((error, i)=><p key={i}>{error}</p>)
}
isFormValid = () =>{
let errors = [];
let error;
if(this.isFormEmpty(this.state)){
error = {message : "Fill in all fields"};
this.setState({errors: errors.concat(error)});
}else if(!this.isPasswordValid(this.state)){
error = {message:"Password is invalid"};
this.setState({errors:errors.concat(error)});
}else{
return true;
}
}
isPasswordValid= ({password, passwordConfirmation})=>{
if(password.length <6||passwordConfirmation.length<6){
return false;
} else if(passwordConfirmation!==password){
return false;
}else{
return true;
}
}
isFormEmpty= ({lastname, name, email, password, passwordConfirmation})=>{
return (
!name.length ||
!lastname.length||
!email.length||
!password.length||
!passwordConfirmation.length
);
}
submitForm = event=>{
event.preventDefault();
let dataToSubmit = {
email : this.state.email,
name : this.state.name,
lastname:this.state.lastname,
password : this.state.password,
passwordConfirmation: this.state.passwordConfirmation
}
if(this.isFormValid()){
this.setState({errors:[]});
this.props.disptch(registerUser(dataToSubmit))
.then(response =>{
if(response.payload.success){
this.props.history.push('/login')
}else{
this.setState({
errors:this.state.errors.concat("your attempt to send data to DB was failed")
})
}
})
.catch(err =>{
this.setState({
errors: this.state.errors.concat(err)
})
})
}else{
console.error("Form is not valid");
}
}
render() {
return (
<div className="container">
<div className="row">
<h2>Sign Up</h2>
{/* 전체 사이즈 사용하려면 12사용한다. */}
<form className="col s12" onSubmit={event =>this.submitForm(event)}>
<div className="row">
<div className="input-field col s12">
<input
name="lastname"
value={this.state.lastname}
onChange={e=> this.handleChange(e)}
id="lastname"
type = "text"
className="validate"
/>
<label htmlFor = "email">lastname</label>
<span
className="helper-text"
data-eroor="Type a right type lastname"
data-success="right"
/>
</div>
</div>
<div className="row">
<div className="input-field col s12">
<input
name="name"
value={this.state.name}
onChange={e=> this.handleChange(e) }
id="name"
type = "name"
className="validate"
/>
<label htmlFor = "name">name</label>
<span
className="helper-text"
data-eroor="wrong"
data-success="right"
/>
</div>
</div>
<div className="row">
<div className="input-field col s12">
<input
name="email"
value={this.state.email}
onChange={e=> this.handleChange(e) }
id="email"
type = "email"
className="validate"
/>
<label className = "active" for = "email">email</label>
<span
className="helper-text"
data-eroor="wrong"
data-success="right"
/>
</div>
</div>
<div className="row">
<div className="input-field col s12">
<input
name="password"
value={this.state.password}
onChange={e=> this.handleChange(e) }
id="password"
type = "password"
className="validate"
/>
<label className = "active" for = "password">password</label>
<span
className="helper-text"
data-eroor="wrong"
data-success="right"
/>
</div>
</div>
<div className="row">
<div className="input-field col s12">
<input
name="passwordConfirmation"
value={this.state.passwordConfirmation}
onChange={e=> this.handleChange(e) }
id="passwordConfirmation"
type = "password"
className="validate"
/>
<label className = "active" for = "passwordConfirmation">password Confirmation</label>
<span
className="helper-text"
data-eroor="wrong"
data-success="right"
/>
</div>
</div>
{this.state.errors.length>0 && (
<div>
{this.displayErrors(this.state.errors)}
</div>
)}
<div className="row">
<div className="col s12">
<button
className="btn waves-effect red lighten-2"
type="submit"
name = "action"
onClick={this.submitForm}
>Create an account
</button>
</div>
</div>
</form>
</div>
</div>
)
}
}
export default connect(mapStateToProps)(Register);
src>actions>user_actions.js
import axios from 'axios';
import {
LOGIN_USER,
REGISTER_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
}
};
export function registerUser(dataToSubmit){
const request = axios.post('api/users/register', dataToSubmit)
.then(response => response.data)
return {
type:REGISTER_USER,
payload: request
}
};
src>actions>types.js
export const LOGIN_USER = 'login_user';
export const REGISTER_USER = 'register_user';
src>reducers>user_reducer.js
import {
LOGIN_USER,
REGISTER_USER
} from '../actions/types';
export default function( state = {}, actions){
switch(actions.type){
case LOGIN_USER:
return { ...state, loginSuccess: actions.payload}
case REGISTER_USER:
return { ...state, loginSuccess: actions.payload}
default:
return state;
}
}
functional 방식을 이용한 것은 다음과 같다.
import React, { useState } from 'react'
import { useDispatch } from 'react-redux';
import { registerUser } from '../../../_actions/user_action';
import Axios from 'axios';
import { withRouter } from 'react-router-dom';
function RegisterPage(props) {
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,
password: Password,
name: Name
}
dispatch(registerUser(body))
.then(response => {
if (response.payload.success) {
props.history.push("/login")
} else {
alert("Failed to sign up")
}
})
}
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 type="submit">
회원 가입
</button>
</form>
</div>
)
}
export default withRouter(RegisterPage)
생성된 파일들은 아래의 깃헙에서 확인할 수 있다.
https://github.com/jaewonhimnae/boilerplate-mern-stack
jaewonhimnae/boilerplate-mern-stack
Boilerplate when you use REACT JS, MONG DB, EXPRESS JS, REDUX - jaewonhimnae/boilerplate-mern-stack
github.com