React-hook-form [ register와 useState 동시 상태 관리 예시]

PARKHEECHANG·2023년 9월 24일

React

목록 보기
3/4
post-thumbnail

이메일 자동완성 => useState로 관리
react-hook-form의 register => register('email')의 {onChange}로 관리

import React, { useState } from 'react';

import { UseFormRegister, FieldErrors } from 'react-hook-form';

import { useOutsideClick } from 'hooks/useOutsideClick';
import { EMAIL_DOMAIN } from 'constants/USER_MODIFY';
import { Input } from '@material-tailwind/react';

interface Props {
  register: UseFormRegister<any>;
  errors: FieldErrors;
}

const EmailInput = ({ register, errors }: Props) => {
  const [email, setEmail] = useState('');
  const { onChange, ...rest } = register('email'); // useHookForm
  const [emailList, setEmailList] = useState(EMAIL_DOMAIN); //추천 이메일 리스트를 확인, 이메일 리스트 상태 관리
  const [selected, setSelected] = useState(-1); //키보드 선택
  const [isDrobBox, setIsDropbox] = useState(false); // 드롭박스 유무
  const inputRef = useOutsideClick(() => setIsDropbox(false));

  const onChangeEmail = (e: React.ChangeEvent<HTMLInputElement>) => {
    setEmail(e.target.value);
    if (e.target.value.includes('@')) {
      setIsDropbox(true);
      setEmailList(EMAIL_DOMAIN.filter((el) => el.includes(e.target.value.split('@')[1])));
    } else {
      setIsDropbox(false);
      setSelected(-1);
    }
  };

  const handleDropDownClick = (email: string, domain: string) => {
    setEmail(`${email.split('@')[0]}${domain}`);

    onChange({
      target: {
        value: email,
        name: 'email',
      },
    });

    setIsDropbox(false);
    setSelected(-1);
  };

  const handleKeyUp = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (isDrobBox) {
      if (e.key === 'ArrowDown' && emailList.length - 1 > selected) {
        setSelected(selected + 1);
      }
      if (e.key === 'ArrowUp' && selected >= 0) {
        setSelected(selected - 1);
      }
      if (e.key === 'Enter' && selected >= 0) {
        handleDropDownClick(email, emailList[selected]);
      }
    }
  };

  return (
    <div ref={inputRef}>
      <Input
        type="email"
        label="이메일"
        {...register('email')}
        value={email}
        onChange={(e) => {
          onChange(e); // react-hook-form의 register 상태관리
          onChangeEmail(e); // 자동완성 로직 상태관리
        }}
        onKeyUp={handleKeyUp}
        crossOrigin="anonymous"
      />
      {isDrobBox && (
        <ul className="border-2 fixed bg-back z-10 w-96 rounded">
          {emailList.map((domain, idx) => (
            <li
              key={idx}
              onMouseOver={() => setSelected(idx)}
              onClick={() => handleDropDownClick(email, domain)}
              className={idx === selected ? 'bg-blue-gray-500 text-white border-black border rounded ml-3' : 'ml-3'}
            >
              {email.split('@')[0]}
              {domain}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
};

export default EmailInput;

0개의 댓글