[React] 회원가입 구현 ( stepper, 약관동의, 유효성 검사 )
쇼핑몰 프로젝트를 하면서 회원가입 구현 내용을 기록하고자 한다.
*스타일은 mui로 해줌
📍stepper
참고하는 사이트의 회원가입에서는
약관동의 -> 정보입력 -> 가입완료 순서로 stepper로 회원가입을 보여준다.
그래서 mui의 stepper을 사용하기로 했다.
이건 그냥 가져와서 필요없는 부분만 삭제했다.
step 개념과 Next, Back 버튼을 놔두고 나머지는 버렸다 .
그리고 각 스텝 별로 각각의 컴포넌트를 만들어서 넣어주었다. 이 과정에서 다음 스텝으로 넘어가려면 어떠한 조건을 충족해야 한다.
(약관동의에서 필수 약관을 모두 체크해야 next 버튼을 활성화)
(정보입력에서 각 유효성 검사를 만족한 텍스트필드를 입력했을 때 next 버튼 활성화)
import React, { useState } from 'react';
import { Box, Stepper, Step, StepLabel, Button, Typography, Divider } from '@mui/material';
import Agreement from '../component/Agreement';
import InputSignup from '../component/InputSignup';
const steps = ['약관동의', '정보입력', '가입완료'];
export default function Signup() {
const [activeStep, setActiveStep] = useState(0);
const [isAgreed, setIsAgreed] = useState(false);
const [isValidInput, setIsValidInput] = useState(false);
const handleNext = () => {
setActiveStep((prevActiveStep) => prevActiveStep + 1);
};
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1);
};
const handleAgreementChange = (isChecked) => {
setIsAgreed(isChecked);
};
const handleValidityChange = (isValid) => {
setIsValidInput(isValid);
};
return (
<Box sx={{ width: '100%' }}>
<Typography align='center'>회원가입</Typography>
<Divider sx={{marginBottom:3, }} />
<Stepper activeStep={activeStep}>
{steps.map((label) => (
<Step key={label}>
<StepLabel>{label}</StepLabel>
</Step>
))}
</Stepper>
<Box sx={{ margin:2, height:'auto'}}>
{activeStep === 0 && <Agreement onAgreementChange={handleAgreementChange} />}
{activeStep === 1 && <InputSignup onValidityChange={handleValidityChange} />}
{activeStep === 2 && <Typography>가입이 완료되었습니다!</Typography>}
</Box>
<Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}>
<Button
color="primary"
disabled={activeStep === 0}
onClick={handleBack}
sx={{ mr: 1 }}
>
Back
</Button>
<Box sx={{ flex: '1 1 auto' }} />
<Button onClick={handleNext} disabled={(activeStep === 0 && !isAgreed) || (activeStep === 1 && !isValidInput)}>
{activeStep === steps.length - 1 ? 'Finish' : 'Next'}
</Button>
</Box>
</Box>
);
}
📍약관동의 ( 전체동의, 필수, 선택 )
약관동의 내용은 아직 없는 상태라 우선 체크박스만 가져와서 구현했다.
✔️ 요구사항
- 전체 동의를 눌렀을 때 모두 체크되어야 하고 하나라도 해제되었을 경우 전체동의의 체크도 해제
- 필수 약관을 모두 체크해야 next 버튼을 활성화시켜주는 함수 넘겨주기
- 선택은 그냥 뭐 없을 것 같당..
구글링해보니까 다들 const data = [ id:0, title:ddf,, ... ] 데이터를 받아서 하던데 일단 나는 데이터도 없고 ,, 그냥 체크박스만 확인해보는 거니까 ,,? 이대로 진행
전체 동의 - handleAllChecked
필수 - handleRequiredChange
선택 - handleOptionalChange
각각의 함수를 만들어서 요구사항을 충족시켜주었다.
const handleAllChecked = (event) => {
const isChecked = event.target.checked;
setAllChecked(isChecked);
setRequiredChecked({
필수1: isChecked,
필수2: isChecked,
});
setOptionalChecked(isChecked);
};
const handleRequiredChange = (event) => {
const { name, checked } = event.target;
setRequiredChecked((prevState) => ({
...prevState,
[name]: checked,
}));
};
const handleOptionalChange = (event) => {
setOptionalChecked(event.target.checked);
};
allRequiredChecked 라는 함수를 만들어서 useEffect()로 조건에 만족하면 onAgreementChange를 props로 버튼 활성화 상태를 업데이트해준다.
📍회원가입 - 유효성 검사
회원가입 유효성검사와 관련된 포스팅이 아주 많아서 그 중에 가장 기본적인 구조를 참고해서 구현했다.
useState를 남발하는 듯이 했지만 이게 그래도 직관적인 것 같아서 이렇게 구성했고 이후에 기능별 useState를 묶어서 관리하거나 react-hook-form을 사용해서 리팩토링을 진행해보면 좋을 것 같다.
const [id, setId] = useState('')
const [idError, setIdError] = useState('');
const [isIdValid, setIsIdValid] = useState(false);
const handleIdChange = (e) => {
const value = e.target.value;
setId(value);
if (/^[A-Za-z]{5,}$/.test(value)) {
setIsIdValid(true);
setIdError('');
} else {
setIsIdValid(false);
setIdError('영문으로 5자 이상 입력해주세요');
}
};
//return
<TextField
size="small"
name='id'
label='id'
fullWidth
value={id}
onChange={handleIdChange}
helperText={idError || (isIdValid && '사용가능한 아이디입니다.')}
error={!!idError}/>
이런 식으로 반복해주면 된다.
이것도 마찬가지로 isAllValid 라는 함수를 props로 넘겨주어 next 버튼을 활성화 여부를 알려준다.
이후 서버 연결하면 중복확인 버튼을 이용해서 유효성 검사해주는 것으로 바꿔볼 생각이다!
🙏🏻 회원가입 참고 포스팅
화면에선 안보이지만 전부 유효한 텍스트를 입력해야 next 버튼이 활성화되어 다음 단계로 넘어갑니당./