Skip to content

Form 고려하기 ‐ mypage

LikeFireAndSky edited this page Jan 2, 2024 · 8 revisions

form 제작 고려

1. 닉네임을 입력하면 확인 버튼 활성화 - 입력에 대한 추적 필요 (해결)

  • 원 입력과 무조건 달라야 함

2. 취소를 누르면 원래의 props 닉네임으로 변동해야함 (해결)

  • react hook form reset 활용

3. 규정을 위반하면 확인 버튼 클릭 X (해결)

  • zod 유효성 검사로 확인
console.log(nameSchema.safeParse(watch('nickname')).success);

zod 유효성 검사가 다 false로 나옴

😊 해결 zod는 객체를 비교. 따라서

 const availableNickname = nameSchema.safeParse({
    nickname: inputText,
  }).success;

이렇게 해주어야 함.

4. 너무 많은 함수 실행 => debounce 필요 (해결)

lodahs-es 사용

  const inputText = watch('nickname');

  const notSameNickname = inputText !== name;

  const availableNickname = nameSchema.safeParse({
    nickname: inputText,
  }).success;

  const isNickname = notSameNickname && availableNickname;

  console.log(isNickname);

이 기능들을 최적화 해야함

inputText가 변경될 때마다 함수가 실행, 나머지 함수들을 묶어야 함.

  const checkNickname = (nickname: string) => {
    const notSameNickname = inputText !== name;

    const availableNickname = nameSchema.safeParse({
      nickname: inputText,
    }).success;

    return notSameNickname && availableNickname;
  };

처음 함수만 실행. 따라서 useEffect 사용 필요

  useEffect(() => {
    const checkNickname = () => {
      const notSameNickname = inputText !== name;

      const availableNickname = nameSchema.safeParse({
        nickname: inputText,
      }).success;

      return notSameNickname && availableNickname;
    };

    if (checkNickname()) {
      console.log('available');
    } else {
      console.log('not available');
    }
  }, [inputText, name]);

해당 상태를 저장할 useState가 필요.

  const inputText = watch('nickname');

  useEffect(() => {
    const checkNickname = () => {
      const notSameNickname = inputText !== name;

      const availableNickname = nameSchema.safeParse({
        nickname: inputText,
      }).success;

      return notSameNickname && availableNickname;
    };

    if (checkNickname()) {
      console.log('available');
      setCheckNickname(true);
    } else {
      console.log('not available');
    }
  }, [inputText, name]);

useEffect와 useState를 사용

debounce를 걸기 위해 custom hook 제작. watch 자체를 debounce 걸 수 없어서 따로 text를 받는 hook으로 제작

import React, { useEffect } from 'react';

export const useDebounceText = (text: string, delay: number) => {
  const [debounceText, setDebounceText] = React.useState(text);

  useEffect(() => {
    const timer = setTimeout(() => {
      setDebounceText(text);
    }, delay);

    return () => {
      clearTimeout(timer);
    };
  }, [text, delay]);
  return debounceText;
};

해당 hook에 watch로 받아온 text 값을 넣고, 해당 변수를 useEffect의 의존성 배열에 넣어서 활용.

5. zod 에러 불가 (해결)

zod 폼 에러를 인식하지 못하고 있음

image

react-hook-form에서는 validation을 submit 전에 할 수 있는 기능이 있다.

특히 에러를 찾을 때 사용할 수 있다.

해당 기능은 다양한 모드를 지원하는데 여기서 문제가 발생했다.

기본 값은 onBlur이다. input창이 blur처리될 때 발생한다. 즉 input창에 커서가 계속 가 있으면 에러가 발생하지 않는다. (focus 상태이기 때문에)

따라서 변하는 즉시 error 핸들링을 해줘야 한다면

  const {
    register,
    handleSubmit,
    watch,
    reset,
    formState: { errors },
  } = useForm<FormName>({
    resolver: zodResolver(nameSchema),
    mode: 'onChange',
    defaultValues: {
      nickname: name,
    },
  });

다음과 같이 mode를 onChange로 변경해줘야 한다. 이렇게 하면 즉시 error처리를 할 수 있다. 즉 focus된 상태에서도 유효성 검사를 진행할 수 있다. 그러나 성능 면에서 영향을 미칠 수 있다. (모든 검사를 하기 때문에)