지금까지 로그인 모달창을 Redux를 사용하여 전역 상태관리 하였다. 이번에는 useState
를 활용하여 이메일 로그인을 구현해 보자. 이메일 로그인 로직은 다음과 같다.
handleChangeEmail
및 handleChangePassword
함수가 호출되어 이메일과 비밀번호 상태가 업데이트된다.handleChangeEmail
함수에서 이메일이 비어있지 않고 형식이 잘못된 경우 경고 메시지가 표시된다.handleChangePassword
함수에서 비밀번호가 비어있는지 확인한다. 비어있는 경우 경고 메시지가 표시된다.handleSubmit
함수가 호출되어 입력된 이메일과 비밀번호를 검사한다.isLoginError
상태를 true로 설정하여 경고 메시지를 표시한다.이 과정을 통해 사용자는 이메일 주소와 비밀번호를 입력하여 로그인을 시도할 수 있으며, 입력 값에 문제가 있는 경우 적절한 경고 메시지를 통해 피드백을 받을 수 있다.
실제 구현된 코드를 보자.
// src/components/Login/EmailLogin.jsx
import React from 'react';
import WarningMsg from '../WarningMsg/WarningMsg.jsx';
import {
EmailLoginContainer,
EmailLabel,
PasswordLabel,
EmailInput,
PasswordInput,
LoginBtn,
} from './EmailLoginStyle.js';
const EmailLogin = ({
email,
password,
handleChangeEmail,
handleChangePassword,
isEmailEmpty,
isEmailInvalid,
isPasswordEmpty,
isLoginError,
}) => {
return (
<EmailLoginContainer>
<EmailLabel htmlFor='user-email'>이메일</EmailLabel>
<EmailInput
type='text'
id='user-email'
name='user-email'
placeholder='이메일을 입력해주세요.'
value={email}
onChange={handleChangeEmail}
error={isEmailEmpty || isEmailInvalid}
/>
<WarningMsg show={isEmailEmpty} message='이메일을 입력해 주세요.' />{' '}
<WarningMsg
show={isEmailInvalid}
message='이메일 형식에 맞게 입력해 주세요.'
/>{' '}
<PasswordLabel htmlFor='user-pw'>비밀번호</PasswordLabel>
<PasswordInput
type='password'
id='user-pw'
name='user-pw'
placeholder='비밀번호를 입력해주세요.'
value={password}
onChange={handleChangePassword}
error={isPasswordEmpty || isLoginError}
/>
<WarningMsg show={isPasswordEmpty} message='비밀번호를 입력해 주세요.' />{' '}
<WarningMsg
show={isLoginError}
message='로그인 정보가 올바르지 않습니다. 다시 시도해 주세요.'
/>
<LoginBtn type='submit'>로그인</LoginBtn>
</EmailLoginContainer>
);
};
export default EmailLogin;
// src/components/Login/LoginModal/LoginModal.jsx
import React, { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { hideLoginModal } from '../../../store/actions';
import BaseModal from '../../helpers/BaseModal.jsx';
import EmailLogin from '../EmailLogin.jsx';
import {
LoginModalContent,
LoginModalText,
SignupBtn,
// KakaoBtn,
OrText,
} from './LoginModalStyle';
import KakaoLoginBtn from '../KakaoLoginBtn.jsx';
const LoginModal = () => {
const isLoginModalVisible = useSelector(state => state.isLoginModalVisible);
const dispatch = useDispatch();
const handleHideLoginModal = () => {
dispatch(hideLoginModal());
};
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [isEmailEmpty, setIsEmailEmpty] = useState(false);
const [isEmailInvalid, setIsEmailInvalid] = useState(false);
const [isPasswordEmpty, setIsPasswordEmpty] = useState(false);
const [isLoginError, setIsLoginError] = useState(false);
const handleChangeEmail = event => {
setEmail(event.target.value);
console.log(event.target.value);
// 이메일이 비어있지 않고 형식이 잘못된 경우에만 경고 메시지 표시
if (event.target.value !== '' && !validateEmail(event.target.value)) {
setIsEmailInvalid(true);
} else {
setIsEmailInvalid(false);
}
// 이메일이 비어있는지 여부 확인
setIsEmailEmpty(event.target.value === '');
};
const validateEmail = email => {
const regex = /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/;
return regex.test(email);
};
const handleChangePassword = event => {
setPassword(event.target.value);
console.log(event.target.value);
// 패스워드가 비어있는지 확인
setIsPasswordEmpty(event.target.value === '');
};
const handleSubmit = async event => {
event.preventDefault();
if (email === '') {
setIsEmailEmpty(true);
} else {
setIsEmailEmpty(false);
}
if (email !== '' && !validateEmail(email)) {
setIsEmailInvalid(true);
} else {
setIsEmailInvalid(false);
}
if (password === '') {
setIsPasswordEmpty(true);
} else {
setIsPasswordEmpty(false);
}
// 입력이 올바르지 않은 경우에는 로그인 시도를 중단
if (isEmailEmpty || isEmailInvalid || isPasswordEmpty) {
return;
}
// 이메일과 패스워드가 존재하지 않을떄 로직 추가
try {
console.log(email, password);
} catch (error) {
setIsLoginError(true);
}
};
return (
<BaseModal
isVisible={isLoginModalVisible}
onClose={handleHideLoginModal}
title='로그인 또는 회원가입'
>
<LoginModalContent onSubmit={handleSubmit}>
<LoginModalText>☕️ 카페골목에 오신 것을 환영합니다.</LoginModalText>
<EmailLogin
email={email}
password={password}
handleChangeEmail={handleChangeEmail}
handleChangePassword={handleChangePassword}
handleSubmit={handleSubmit}
isEmailEmpty={isEmailEmpty}
isEmailInvalid={isEmailInvalid}
isPasswordEmpty={isPasswordEmpty}
isLoginError={isLoginError}
/>
<OrText>또는</OrText>
<KakaoLoginBtn />
<SignupBtn type='button'>카페골목 회원가입 하기</SignupBtn>
</LoginModalContent>
</BaseModal>
);
};
export default LoginModal;
// src/components/WarningMsg/WarningMsg.jsx
import React from 'react';
import styled from 'styled-components';
import { palette } from '../../styles/globalColor';
export const WarningMsgContainer = styled.strong`
display: block;
margin-left: 5px;
margin-bottom: 10px;
font-size: 13px;
color: ${palette.redColor};
display: ${props => (props.show ? 'block' : 'none')};
`;
const WarningMsg = ({ show, message }) => (
<WarningMsgContainer show={show}>{message}</WarningMsgContainer>
);
export default WarningMsg;