-
MERN 기본파일 만들기 - 12) Login Page 만들기NODE.JS 2021. 5. 13. 15:05
컴포넌트 안의 registerlogin을 이용할 것이다.
App.js에 라우터를 등록해 놓는다.
import React from 'react'; import {Route, Switch} from "react-router-dom"; import About from "./about"//index.js가 기본이기 때문에 굳이 타이핑하지 않아도 된다. import LoginPage from "./RegisterLogin/LoginPage"; import RegisterPage from "./RegisterLogin/RegisterPage"; import LandingPage from "./ function App() { return ( <div > <Switch> {/* <Route path="/" component={Home} /> */} <Route path = "/" component={LandingPage}/> <Route path = "/login" component={LoginPage}/> <Route path = "/register" component={RegisterPage}/> </Switch> </div> ); } export default App;
먼저 class 방식을 보자.
src>components>RegisterLogin>index.js
import React, { Component } from 'react' class RegisterLogin extends Component { } export default connect(mapStateToProps)(RegisterLogin);
css 스타일링은 materialize를 이용한다.
https://materializecss.com/getting-started.html
client에 npm install materialize-css@next --save해준다.
그다음 src>components>registerLogin>index.js를 다음과 같이 바꾼다.
handleChange 는 값을 입력하면 그대로 바로 화면에 보여주게끔 해주는 함수이고,
submitForm은 들어온 값이 validate하다면 데이터를 보내서 아이디와 비밀번호가 맞는지 확인하고
isFormvalid는 입력한 형식이 맞는지 확인하는 함수이다.
event.preventDefault()는 창 새로고침이 계속되는 것을 막아준다.
import React, { Component } from 'react' import {connect} from 'react-redux'; import {loginUser} from '../../actions/user_actions';//actions에서 response를 가지고 있기 때문에 loginUser를 가져온다. import {Link} from 'react-router-dom'; class RegisterLogin extends Component { state = { email:"", password: "", errors:[] } displayErrors = errors=>{ errors.map((error, i)=><p key={i}>{error}</p>) } handleChange = event =>{ this.setState({[event.target.name]: event.target.value}) } submitForm = event=>{ event.preventDefault(); let dataToSubmit = { email:this.state.email, password:this.state.password }; if(this.isFormvalid(this.state)){ this.setState({errors:[]}) this.props.dispatch(loginUser(dataToSubmit))//actions의 함수 loginUser .then(response=>{ if(response.payload.loginSuccess){ this.props.history.push('/') }else{ this.setState({errors: this.state.errors.concat("Failed to log in, you can check your email and password")}) } } ) }else{ this.setState({ errors: this.state.errors.concat('Form is not valid') }) } } isFormvalid=({email, password}) => email && password; // const {email} = this.state; // const email = this.state.email; 위아래는 같은 뜻이다. render() { return ( <div className="container"> <div className="row"> <h2>Login</h2> {/* 전체 사이즈 사용하려면 12사용한다. */} <form className="col s12" onSubmit={event =>this.submitForm(event)}> <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 htmlFor = "email">Email</label> <span className="helper-text" data-eroor="Type a right type email" 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 htmlFor = "password">Email</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} >Login </button> {/* a href 는 계속 새로 새로고침하고 Link는 하지 않는다.*/} <Link to = "/register"> <button className="btn waves-effect red lighten-2" type="submit" name = "action" >Sign up </button> </Link> </div> </div> </form> </div> </div> ) } } function mapStateToProps(state){ return { user:state.user } } export default connect(mapStateToProps)(RegisterLogin);
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) //리듀서는 들어온 정보와 현재정보를 조합하여 다음 조합을 리턴한다. (액션은 response와 타입을 피요로 하므로 다음과 같이 넣어준다) return { type:LOGIN_USER, payload: request } };
src>actions>types.js
//타입만 관리하는 type파일 export const LOGIN_USER = 'login_user';
reducer>user_reducers.js
import { LOGIN_USER, } from '../actions/types'; export default function( state = {}, actions){//전 state와 action가지고 다음 step을 만든다 switch(actions.type){//타입에 따라서 다른 처리 한다. case LOGIN_USER: return { ...state, loginSuccess: actions.payload} default: return state; } }
이번엔 functional 방식으로 진행해보자.
LoginPage.js는 다음과 같다.
import React, { useState } from 'react' import Axios from 'axios' import { useDispatch } from 'react-redux'; import { loginUser } from '../../../_actions/user_action'; import { withRouter } from 'react-router-dom'; function LoginPage(props) { 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 } //서버에 보낼것인데, axios를 리덕스를 이용해서 진행할 것이다. dispatch(loginUser(body)) .then(response => { if (response.payload.loginSuccess) {//성공하면 메인페이지로 이동 props.history.push('/') } else { alert('Error˝') } }) } 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 type="submit"> Login </button> </form> </div> ) } export default withRouter(LoginPage)
RegisterPage.js는 다음과 같다
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)
'NODE.JS' 카테고리의 다른 글
Youtube 만들기 - 2) 비디오 업로드 Form 만들기 1 (0) 2021.05.14 MERN 기본파일 만들기 - 13)Register Page 만들기 (0) 2021.05.13 MERN 기본파일 만들기 - 11)antd 디자인 사용하기, redux 사용하기, React-Hooks (0) 2021.05.13 MERN 기본파일 만들기 - 10) proxy, concurrently 사용하기 (0) 2021.05.13 MERN 기본파일 만들기 - 9) react app, axios, router-dom 사용하기 (0) 2021.05.13