(1) 필수사항
- 이메일 입력
- 비밀번호 입력
- 로그인 버튼
- 회원가입 버튼
(2) 예외처리
이메일, 비밀번호 입력후 로그인 버튼 활성화 처리(맨 처음엔 비활성화)
(3) UI만 구현
회원가입 버튼
<div className="login">
<div className="userFrame" onChange={handleInputChange}>
...생략...
<UserInput
type="text"
placeholder="이메일"
value={userInfo.email}
name="email"
/>
<UserInput
type="password"
placeholder="비밀번호"
value={userInfo.password}
name="password"
/>
...생략
</div>
</div>
import React from 'react';
import './UserInput.scss';
const UserInput = ({ type, placeholder, value, name, onChange }) => {
return (
<input
className="userInput"
type={type}
placeholder={placeholder}
onChange={onChange}
value={value}
name={name}
/>
);
};
export default UserInput;
...생략...
<UserButton
text="로그인"
disabled={!isInvaild}
onClick={loginProgcess}
/>
<div className="buttonWrapper">
<button className="actionButton" onClick={goSignupPage}>
회원 가입
</button>
<div className="wall">|</div>
<button className="actionButton">비밀번호 찾기</button>
</div>
...생략...
import React from 'react';
import './UserButton.scss';
const UserButton = ({ text, onClick, disabled }) => {
return (
<button className="userButton" onClick={onClick} disabled={disabled}>
{text}
</button>
);
};
export default UserButton;
// 유저 정보(ID, PW)
const [userInfo, setUserInfo] = useState({
email: '',
password: '',
});
// 이메일, 비밀번호
const handleInputChange = event => {
const { name, value } = event.target;
setUserInfo(userInfo => ({
...userInfo,
[name]: value,
}));
};
...
<div className="userFrame" onChange={handleInputChange}>
...생략...
<UserInput
type="text"
placeholder="이메일"
value={userInfo.email}
name="email"
/>
<UserInput
type="password"
placeholder="비밀번호"
value={userInfo.password}
name="password"
/>
<UserButton
text="로그인"
disabled={!isInvaild}
onClick={loginProgcess}
/>
...생략...
</div>
이 로직은 사용자의 이메일과 비밀번호를 저장하고 업데이트하는 기능을 수행한다. 'userInfo' 상태에 이메일과 비밀번호를 객체 형태로 저장하여 관리하고, 'handleInputChange' 함수는 사용자가 입력한 값이 이 상태에 반영될 수 있도록 한다. 또한 사용자가 UserInput에 이메일 또는 비밀번호를 입력할 때마다 'userInfo' 상태가 업데이트되어, 이를 통해 입력된 값이 UserButton(로그인) 버튼을 활성화 시킨다.
(이벤트 위임이란? 이벤트가 발생하는 요소마다 이벤트(onChange)에 핸들러 함수를 전달할 필요 없이, 감싸고 있는 상위 요소에 한번만 이벤트에 핸들러 함수를 전달하면, 자식 요소의 이벤트를 전부 감지할 수 있는 기능을 수행한다.)
// 유효성 검사
const isInvaild =
userInfo.email.includes('@') &&
userInfo.email.includes('.') &&
userInfo.password.length >= 10;
...
<UserButton
text="로그인"
disabled={!isInvaild}
onClick={loginProgcess}
/>
// 페이지 이동
const navigate = useNavigate();
// 회원가입 페이지 이동
const goSignupPage = () => {
navigate('/signup');
};
...
<div className="buttonWrapper">
<button className="actionButton" onClick={goSignupPage}>
회원 가입
</button>
...생략...
</div>
(6) 로그인 페이지 - fetch 메서드로 회원 정보 요청하기
// fetch : 로그인 버튼 클릭시 메인 페이지로 이동
const loginProgcess = () => {
fetch('/data/Login.json', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8',
},
body: JSON.stringify({
email: userInfo.email,
password: userInfo.password,
}),
})
.then(response => response.json())
.then(data => {
if (data.message === 'LOGIN SUCCESS') {
alert('로그인 되었습니다.');
localStorage.setItem('token', data.message);
navigate('/main');
} else {
alert('가입되지 않은 정보입니다.');
}
});
};
...
<UserButton
text="로그인"
disabled={!isInvaild}
onClick={loginProgcess}
/>
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import UserInput from '../../Components/UserInput';
import UserButton from '../../Components/UserButton';
import './Login.scss';
const Login = () => {
// 유저 정보(ID, PW)
const [userInfo, setUserInfo] = useState({
email: '',
password: '',
});
// 이메일, 비밀번호
const handleInputChange = event => {
const { name, value } = event.target;
setUserInfo(userInfo => ({
...userInfo,
[name]: value,
}));
};
// 유효성 검사
const isInvaild =
userInfo.email.includes('@') &&
userInfo.email.includes('.') &&
userInfo.password.length >= 10;
// 페이지 이동
const navigate = useNavigate();
// 회원가입 페이지 이동
const goSignupPage = () => {
navigate('/signup');
};
// fetch : 로그인 버튼 클릭시 메인 페이지로 이동
const loginProgcess = () => {
fetch('/data/Login.json', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8',
},
body: JSON.stringify({
email: userInfo.email,
password: userInfo.password,
}),
})
.then(response => response.json())
.then(data => {
if (data.message === 'LOGIN SUCCESS') {
alert('로그인 되었습니다.');
localStorage.setItem('token', data.message);
navigate('/main');
} else {
alert('가입되지 않은 정보입니다.');
}
});
};
return (
<div className="login">
<div className="userFrame" onChange={handleInputChange}>
<div className="imageFrame">
<img className="logo" src="/images/Logo.svg" alt="위코드 로고" />
<img
className="logo"
src="/images/logo_wecode.svg"
alt="위코드 로고"
/>
</div>
<UserInput
type="text"
placeholder="이메일"
value={userInfo.email}
name="email"
/>
<UserInput
type="password"
placeholder="비밀번호"
value={userInfo.password}
name="password"
/>
<UserButton
text="로그인"
disabled={!isInvaild}
onClick={loginProgcess}
/>
<div className="buttonWrapper">
<button className="actionButton" onClick={goSignupPage}>
회원 가입
</button>
<div className="wall">|</div>
<button className="actionButton">비밀번호 찾기</button>
</div>
</div>
</div>
);
};
export default Login;