일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 자바스크립트로 알아보는 함수형 프로그래밍
- React
- 개발자 독서
- 프로그래머의 길
- 웹 성능 최적화
- 성능 최적화
- Concurrent UI Pattern
- javascript 순수 함수
- javascript 이메일 자동완성
- javascript
- 멘토에게 묻다
- 로딩 최적화
- UI 개발 패턴
- 일급 함수
- 프러그래머의 길 멘토에게 묻다
- 자바스크립트
- javascript email
- Concurrent 모드
- 함수형 프로그래밍
- js 함수형 프로그래밍
- useState 동작원리
- javascript 함수형 프로그래밍
- React 성능
- React 성능 최적화
- 에니메이션 최적화
- react 선언형
- javascript 일급 함수
- 디바운싱
- 클로져
- react 명령형
- Today
- Total
Hengxi's 개발 블로그
[React] 이메일 자동완성 기능 구현하기 본문
현재 진행하는 프로젝트에서 이메일 자동완성 기능을 필요로 하여 기능 구현을 해보았다.
처음에는 구글링을 하면 간단하게 구현할 수 있을 것이라고 생각했지만, 이메일 자동 완성 기능을 구현해 놓은 코드는 없었다...
그래서 HTML에 datalist 태그를 이용하여 간단하게 구현을 했는데, 안타깝게도 스타일을 줄 수 없어 빠꾸 먹고... javascript로 열심히 기능을 구현했다.
아래는 쿠팡의 로그인 화면으로 이메일 자동완성 기능을 쿠팡처럼 구현하고자 했다.
자주 사용하는 이메일 리스트와 기능 구현에 필요한 state 선언
const FrequencyEmails = [
'@naver.com',
'@gmail.com',
'@daum.net',
'@hanmail.net',
'@yahoo.com',
'@outlook.com',
'@nate.com',
'@kakao.com',
];
const [email, setEmail] = useState(defaultEmail); //이메일 input 값
const [emailList, setEmailList] = useState(FrequencyEmails); //추천 이메일 리스트를 확인, 이메일 리스트 상태 관리
const [selected, setSelected] = useState(-1); //키보드 선택
const [isDrobBox, setIsDropbox] = useState(false); // 드롭박스 유무
const inputRef = useRef(); //외부클릭 감지 확인
함수 만들기
외부 클릭 감지
useEffect(() => {
const handleClickOutside = (e) => {
if (
inputRef.current &&
!inputRef.current.contains(e.target)
) {
setIsDropbox(false);
}
};
document.addEventListener('mousedown', handleClickOutside);
}, [inputRef]);
input 태그와 dropbox를 감싸고 있는 div에 ref를 주었다.(input에 ref를 주고 dropbox를 선택하려 하면 dropbox가 사라짐)
useEffect를 활용하여 외부 클릭(mousedown) 감지, ref를 벗어난 클릭이면 isDropBox를 false로 바꿔주었다.
이메일 값 담기 드롭박스 상태 관리
const onChangeEmail = (e) => {
setEmail(e.target.value);
if (e.target.value.includes('@')) {
setIsDropbox(true);
setEmailList(
FrequencyEmails.filter((el) =>
el.includes(e.target.value.split('@')[1]),
),
);
} else {
setIsDropbox(false);
setSelected(-1);
}
};
input에 onChange이벤트로 email state에 값을 담아 주는 동시에 isDropBox를 true로 바꿔주었다. @를 입력해야 이메일 리스트가 나오도록 구현하기 위해 if문을 사용하여 분기 처리를 했다.
input창에 한 글자만 써도 이메일을 리스트업 해주는 사이트들이 있는데, 이러한 구현을 원한다면 if문의 조건을 조금만 수정해주면 될 듯
emailList에는 입력된 값을 포함하는 List만을 걸러주기 위해 filter와 includes를 사용, 입력 값 중 @ 이후만 필요하니 split을 사용하였다.
드롭박스 클릭 선택
const handleDropDownClick = (first, second) => {
setEmail(`${first.split('@')[0]}${second}`);
setIsDropbox(false);
setSelected(-1);
};
드롭박스(이메일 리스트) 마우스로 클릭하면 input에 클릭 값이 들어가는 함수이다. 2개의 파라미터를 받아 합쳐 주고 있는데 첫 번째가 전체 input값이기 때문에 @ 앞부분만 가져오기 위하여 split을 사용('test@na'라는 값을 input에 입력 후 드롭박스 선택했을 때 첫 번째 값이 test@na가 되기때문), 두 번째 파라미터는 선택한 emailList 값이 들어가게 된다.
클릭하면 input에 입력 후 드롭박스를 제거해주기 위해 dropBox 상태를 false로 바꿔주고, selected 값도 원위치시켜준다.(아래에서 추가 설명)
키보드로 드롭박스 선택
const handleKeyUp = (e) => {
if (isDrobBox) {
if (e.key === 'ArrowDown' && emailList.length - 1 > selected) {
setSelected(selected + 1);
}
//emailList.length에 -1을 해주는 이유는 selected의 최대값을 맞춰주기 위해서이다.
//예를들어 밑에 emailList 2개가 나왔다고 가정했을 때, selected값이 최대 1까지 변할 수 있게 해줘야한다.
//'ArrowDown'키를 누르면 selected는 0이 되고, 한번 더 누르면 1이 되고, 그 다음은 더이상 옵션이 없기 때문에 키가 안먹히게 해주는 것이다.
if (e.key === 'ArrowUp' && selected >= 0) {
setSelected(selected - 1);
}
if (e.key === 'Enter' && selected >= 0) {
handleDropDownClick(email, emailList[selected]);
}
}
};
input 값에 @가 있을 때(isDropBox가 true일 경우 / 드롭박스가 보일 경우), 키보드로 emailList를 선택할 수 있게 해주는 함수이다.
selected에 대한 설명은 코드 부분에 적어 두었다. 처음 조건을 이해하였다면 그다음은 바로 이해가 될 것이다.
Enter키를 누르면 handleDropDownClick 함수가 불리기 때문에 인자로 email과 선택된 emailList의 값을 보내준다.
전체 코드
<div ref={inputRef}>
<input
type="email"
placeholder="이메일(아이디) 입력"
value={email}
onChange={(e) => {
onChangeEmail(e);
}}
onKeyUp={handleKeyUp}
/>
{isDrobBox && (
<MailTipUl>
{emailList.map((item, idx) => (
<MailTipLi
key={idx}
onMouseOver={() => setSelected(idx)}
onClick={() => handleDropDownClick(email, item)}
selected={selected === idx}
>
{email.split('@')[0]}
{item}
</MailTipLi>
))}
</MailTipUl>
)}
</div>
드롭박스 li 태그 css
const MailTipLi = styled.li`
background-color: ${({ selected }) => (selected ? '#f5f5f5' : '')};
color: ${({ selected }) => (selected ? 'var(--zu--m4-color)' : '')};
`;
관련없는 코드는 지우고 올렸습니다.
isDropBox가 true일 경우 드롭박스가 보이도록 설정했다. 처음에는 hover로도 css를 주었는데, 키보드로 List를 고를 때와 마우스로 고를 때 스타일이 둘 다 먹어 고민하다 onMouseOver 이벤트를 이용하여 selected 상태를 바꿔주도록 했다.
selected가 idx와 같을 경우 스타일이 먹도록 설정!
그리고 li 태그의 값이 {email}이 아니고 {email.split('@')[0]}{item} 인 것은 위에서 설명하였으니 패스! 쳐보면 바로 알 수 있다.
'개발 > React' 카테고리의 다른 글
[React] useState의 동작원리 (0) | 2022.11.13 |
---|---|
[React] Concurrent UI Pattern 이란 (UI 개발 패턴) (0) | 2022.11.06 |
[React] 웹 성능 최적화하기 2 (0) | 2022.11.03 |
[React] 웹 성능 최적화하기 1 (0) | 2022.10.25 |
[React] Image crop 기능 구현하기 (3) | 2022.10.17 |