회원가입 구현하기React+REST API 게시판 구현/FE - React2021. 9. 29. 20:27
Table of Contents
What to do?
- meterial-ui의 기본적인 input을 가져다 쓰고 formik을 통해서 form의 state 관리를 하고 yup을 사용해서 form의 validation을 검증하자.
- form의 validation 검증이 끝나면 axios로 회원가입을 처리하는 API에 POST 방식으로 데이터를 보내서 서버에 유저의 정보를 저장한다.
- 사용 url: /sign-up
- 회원가입에 성공하면 react-toastify로 2초동안 toast 알림창을 띄우고 /login 으로 이동하게 하자!
- 회원가입 성공 시 DB에 반영이 되는 모습이다!
회원가입 페이지 구현
- pages 디렉토리 아래 sign-up 디렉토리를 만들고 Sigup.js 파일과 singUp.scss 파일을 만들자.
pages/sign-up/SignUp.js
- formik과 yup으로 form의 state 관리 및 유효성 검증을 하고 회원가입을 하는 API 호출 시, 오류가 없으면 toast 알림을 2초간 띄운 뒤 /login (로그인 페이지)으로 이동시키자
- 그리고 Formik의 validOnMount를 사용하여 마운트가 되자마자 error message를 띄워보도록 하자!
- yup의 validationSchema를 정의할 때 regax라는 문법을 사용하는데 이를 사용하면 매우매우 편리하다 ㅎㅎ
import axios from "axios";
import {toast, ToastContainer} from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import {Formik, ErrorMessage} from "formik";
import * as Yup from "yup";
import {Button, TextField} from "@mui/material";
import {useNavigate} from "react-router-dom";
import "./signUp.scss";
const SignUp = () => {
const navigate = useNavigate();
const validationSchema = Yup.object().shape({
email: Yup.string()
.email("올바른 이메일 형식이 아닙니다!")
.required("이메일을 입력하세요!"),
username: Yup.string()
.min(2, "닉네임은 최소 2글자 이상입니다!")
.max(10, "닉네임은 최대 10글자입니다!")
.matches(
/^[가-힣a-zA-Z][^!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?\s]*$/,
"닉네임에 특수문자가 포함되면 안되고 숫자로 시작하면 안됩니다!"
)
.required("닉네임을 입력하세요!"),
password: Yup.string()
.min(8, "비밀번호는 최소 8자리 이상입니다")
.max(16, "비밀번호는 최대 16자리입니다!")
.required("패스워드를 입력하세요!")
.matches(
/^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?])[^\s]*$/,
"알파벳, 숫자, 공백을 제외한 특수문자를 모두 포함해야 합니다!"
),
password2: Yup.string()
.oneOf([Yup.ref("password"), null], "비밀번호가 일치하지 않습니다!")
.required("필수 입력 값입니다!"),
});
const submit = async (values) => {
const {email, username, password} = values;
try {
await axios.post("/api/auth/signup", {
email,
username,
password,
});
toast.success(<h3>회원가입이 완료되었습니다.<br/>로그인 하세요😎</h3>, {
position: "top-center",
autoClose: 2000
});
setTimeout(()=> {
navigate("/login");
}, 2000);
} catch (e) {
// 서버에서 받은 에러 메시지 출력
toast.error(e.response.data.message + "😭", {
position: "top-center",
});
}
};
return (
<Formik
initialValues={{
email: "",
username: "",
password: "",
password2: "",
}}
validationSchema={validationSchema}
onSubmit={submit}
validateOnMount={true}
>
{({values, handleSubmit, handleChange, errors}) => (
<div className="signup-wrapper">
<ToastContainer/>
<form onSubmit={handleSubmit} autoComplete="off">
<div className="input-forms">
<div className="input-forms-item">
<div className="input-label">이메일</div>
<TextField
value={values.email}
name="email"
variant="outlined"
onChange={handleChange}
/>
<div className="error-message">
{errors.email}
</div>
</div>
<div className="input-forms-item">
<div className="input-label">닉네임</div>
<TextField
value={values.username}
name="username"
variant="outlined"
onChange={handleChange}
/>
<div className="error-message">
{errors.username}
</div>
</div>
<div className="input-forms-item">
<div className="input-label">비밀번호</div>
<TextField
value={values.password}
name="password"
variant="outlined"
type="password"
onChange={handleChange}
/>
<div className="error-message">
{errors.password}
</div>
</div>
<div className="input-forms-item">
<div className="input-label">비밀번호 확인</div>
<TextField
value={values.password2}
name="password2"
variant="outlined"
type="password"
onChange={handleChange}
/>
<div className="error-message">
{errors.password2}
</div>
</div>
<Button
color="primary"
variant="contained"
fullWidth
type="submit"
>
회원가입
</Button>
</div>
</form>
</div>
)}
</Formik>
);
};
export default SignUp;
pages/signUp/signUp.scss
- rem을 이용해서 input form의 글씨 크기를 반응형으로 만들고 미디어 쿼리를 사용해서 input의 너비를 반응형으로 만들자!
@media all and (min-width: 1024px) {
.input-forms {
padding: 70px;
input{
width: 400px;
}
}
}
@media all and (max-width: 1024px) {
.input-forms {
padding: 60px;
input{
width: 330px;
}
}
}
@media all and (max-width: 768px) {
.input-forms {
padding: 50px;
input{
width: 300px;
}
}
}
.signup-wrapper {
font-family: 'Noto Sans KR', sans-serif;
display: flex;
flex-direction: column;
align-items: center;
.input-forms {
background-color: #ffffff;
border-radius: 10px;
display: flex;
flex-direction: column;
.input-label {
font-size: 1.2rem;
font-weight: bold;
color: #282c34;
}
.input-forms-item {
padding: 7px 0;
.error-message {
font-size: 1rem;
color: blue;
font-weight: bold;
}
}
}
}
라우팅 추가하기
App.js
- /sign-up url로 진입했을 때 App.js에서 SignUp 컴포넌트를 보여주자
import React from "react";
import {Routes, Route} from "react-router-dom"
import Header from "./components/Header";
import Home from "./pages/home/Home";
import SignUp from "./pages/sign-up/SignUp";
const App = () => {
return (
<React.Fragment>
<Header/>
<Routes>
<Route path="/" element={<Home/>}/>
<Route path="/sign-up" element={<SignUp/>}/>
</Routes>
</React.Fragment>
)
}
export default App
'React+REST API 게시판 구현 > FE - React' 카테고리의 다른 글
게시물 등록하기 페이지 구현 (0) | 2021.10.11 |
---|---|
axios interceptor 구현하기 (0) | 2021.10.04 |
인증 처리하기+PrivateRoute+로그아웃 (0) | 2021.10.04 |
로그인 구현 (redux-persist) (0) | 2021.10.02 |
초반 프로젝트 설정하기 (0) | 2021.09.26 |
@덕구공 :: Duck9s'
주니어 개발자에욤
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!