react-hook-form with typescript react-hook-form을 컴포넌트에 적용해 사용해보자(ps. input창에 아이콘 넣기)

햐얀하늘·2023년 9월 20일
1

react form

  • react에서 form을 사용해 axios를 요청할때 react hook form을 사용하면 여러 번거로운 일들을 확 줄일 수 있다!!
  • form만 사용하지말고 react-hook-form을 한 번 사용해보자!!

react-hook-form 사용이유

  1. 반복성을 줄인다.
    login, 회원가입 등의 일을 하게 될때 input창에 입력데이터를 집어넣고 입력창의 변화를 감지해서 값을 저장해 줘야한다 -> useState와 onChange 함수의 사용이 굉장히 많아짐 -> 코드의 길이가 늘어나고 비슷한 코드 반복

  2. input창에 여러 조건을 줄 수 있다.

  3. 코드가 훨씬 짧아진다 가독성이 증가한다.

  4. 렌더링 상태, 에러 등의 관리가 쉬워진다.

react-hook-form

  1. react-hook-form을 사용할 때에는 input태그에 직접으로 사용하던가
  2. component를 만들어 사용하는 방법 2가지가 있다.

input태그에 직접 사용하는 방식은 아래의 웹사이트를 참고하면 된다.
특히 오픈소스 컨설팅의 글은 매우 상세하게 나와있으니 꼭 읽어보자
https://tech.osci.kr/introduce-react-hook-form/
https://www.daleseo.com/react-hook-form/

component에 활용하는 법도 오픈소스 컨설팅에서 잘 알려준다! 거기다 mui를 사용하는법까지
https://tech.osci.kr/react-hook-form-with-mui/

오픈 소스 컨설팅의 글을 내 프로젝트에 적용해서 정리해서 써보도록 하겠다.

react-hook-form with typescirpt으로 컴포넌트 만들기!!

아이디 입력창을 만들어 활용해 보자

컴포넌트를 만들어 react-hook-form을 사용하기 위해서는 useController를 사용해야한다.

1. import 하기

import styled from 'styled-components';
import { AiOutlineUser } from 'react-icons/ai';
import {
  Control,
  FieldPath,
  FieldValues,
  RegisterOptions,
  useController,
} from 'react-hook-form';

코드를 쓰면서 자동으로 import하는 것이 좋다!!

2. type설정하기

styledinput에 입력되는 값들의 타입을 정해줘야한다!!

export type TControl<T extends FieldValues> = {
  placeholder?: string;
  style?: React.CSSProperties;
  className?: string;
  control: Control<T>;
  name: FieldPath<T>;
  rules?: Omit<
    RegisterOptions<T>,
    'valueAsNumber' | 'valueAsDate' | 'setValueAs' | 'disabled'
  >;
};

3. styled-components를 활용해 input, div태그 꾸미기

const InputContainer = styled.div` //input 태그를 감쌀 컨테이너
  display: flex;
  align-items: center;
  width: 17.125rem;
  height: 4rem;
  background-color: #fff6ec;
`;

const StyledInput = styled.input` // input 입력창
  background-color: #fff6ec;
  padding-left: 2rem;
  border: none; /* 입력란 테두리 제거 */
  outline: none; /* 입력란 포커스 시 외곽선 제거 */
  color: #7d7b7b;
  font-weight: bold;
`;

const Icon = styled(AiOutlineUser)` // 사람 아이콘 추가!
  font-size: 1.5rem;
  flex-shrink: 0;
  color: #7d7b7b;
  margin-left: 10px;
  height: 7rem;
  weight: 7rem;
`;

4. 위의 내용을 토대로 아이디 입력 컴포넌트 만들어보자

React.FC<TControl>에 1형식값이 필요하기 때문에 any를 넣었다.
어떤 타입인지 감이 안잡혀서 any를 넣었는데 더 좋은 타입이 있다면 댓글로 알려주시면 감사하겠습니다.

const StyledIdInputIcon: React.FC<TControl<any>> = ({
  className,
  placeholder,
  style,
  name,
  rules,
  control,
}) => {
  const {
    field: { value, onChange },
  } = useController({ name, rules, control });

  return (
    <InputContainer>
      <Icon />
      <StyledInput
        className={className}
        placeholder={placeholder}
        value={value}
        onChange={onChange}
        style={style}
      />
    </InputContainer>
  );
};

export default StyledIdInputIcon;
  • props로 받아올 값들을 설정해주기!!

className - class설정하기 위해서
placeholder - 기본 입력창에 보여주기 위한것
style - 인라인 css
name - 일반 react-hook-form에서 {...register('여기 들어가는 값', ~~)}
rules - {...register("email",여기에 들어가는 값)} pattern, required 같은 값들이 들어감
ex) 이메일 형식 지정, 이메일 입력 필수값 지정 등
control - 기본 입력 값들

  • useController 사용하기
const {
    field: { value, onChange },
  } = useController({ name, rules, control });

field를 value와 onChange로 나눠주고 name, rules, control을 useController에 있는 것으로 바꿔주기

여기서 value와 onChange는 기존 input에서 사용하는 것과 똑같은 의미로 사용됨
즉 value는 input창의 값을 뜻하고 onChange는 input창의 값이 바뀌는 것을 의미

  • 알맞게 배치하고 props로 받아온 값들 넣어주기
  return (
    <InputContainer>
      <Icon />
      <StyledInput
        className={className}
        placeholder={placeholder}
        value={value}
        onChange={onChange}
        style={style}
      />
    </InputContainer>
  );

컴포넌트 만드는 것은 끝났으니 컴포넌트를 페이지에서 활용해보자

1. page에서 해당 컴포넌트를 사용해보자 타입 설정하기!

interface IForm {
email: string;
}

2. useForm 사용하고 handleLogin 함수 만들어주자

 const {
    register,
    formState: { errors, isSubmitting, isSubmitted },
    handleSubmit,
    control,
  } = useForm<IForm>({
    mode: 'onSubmit',
    defaultValues: {
      email: '',
    },
  });

  const handleLogin: SubmitHandler<IForm> = (data) => { 
    // 여기에 api axios보내는 것을 쓰면됨
  }; 

기본 input태그에서 사용하는것과 거의 똑같다 단!! control이 추가되는 차이가 있다.

3. 컴포넌트 사용하기!!

<form onSubmit={handleSubmit(handleLogin)}> // 제출 버튼 눌러주면 handleLogin을 실행하겠다.
      <div className={classes.inputContainer}> //class이름 정해주기
        {errors.email && ( //에러의 이메일 값이 존재하면 email에 메시지를 띄워준다.
          <small role="alert" style={{ color: 'red', fontSize: '10px' }}>
            {errors.email.message}
          </small>
        )}

        <StyledIdInputIcon
          name="email" // 필드의 이름
          placeholder="이메일" // placeholder
          control={control} // useForm에서 가져온 control
          rules={{ //register에 등록하는 패턴, required같은 조건들
            pattern: {
              value:
                /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i,
              message: '이메일 형식에 맞지 않습니다.', //pattern이 맞지 않을시 출력할 message
            },
          }}
        />
</form>

위의 방식대로 사용하면 된다.

이렇게 사용하면 email에 값이 input창이 바뀔때마다 인식해서 email값이 들어간다.

결과물!!


이렇게 자기가 원하는 input창을 만들어서 react-hook-form을 활용해 간단하게 axios보내보자!!!!

profile
나는 커서 개발자가 될거야!

3개의 댓글

comment-user-thumbnail
2023년 11월 29일

제가 쓴 글 참고해주셨네요~! 감사합니다!!
오늘도 행복한 하루 보내세요 :)

답글 달기
comment-user-thumbnail
2023년 11월 29일

TControl 에는 useController 에 매핑할 타입을 넣어주면 됩니다!

1개의 답글