[TIL 0414] 검증 라이브러리(yup) / 공통컴포넌트 구현하기

zitto·2023년 4월 15일
0

TIL

목록 보기
51/77
post-thumbnail

✔️ yup 이란?

까다로운 검증과정을 대신해주는 라이브러리

보통 form과 함께 사용한다.
따라서 리액트 훅 폼의‘Schema Validation’을 잘 보고 함께 사용할 것

  • 설치명령어
    yarn add yup
    yarn add @hookform/resolvers yup

[실습 section24]

  • index.tsx
import { useForm } from "react-hook-form";
import { wrapFormFunc } from "../../../src/commons/libraries/asyncFunc";
import { yupResolver } from "@hookform/resolvers/yup";
import { schema } from "./02-after.validation";
interface IFormData {
  writer: string;
  title: string;
  contents: string;
  boardAddress: {
    addressDetail: string;
  };
}
export default function GraphqlMutationPage(): JSX.Element {
  //formState에서 에러메세지들을 받아오게 된다.
  const { register, handleSubmit, formState } = useForm<IFormData>({
    resolver: yupResolver(schema),
    mode: "onChange",
  });
	// 등록하기 함수 -> handleSubmit이 조종해주는 함수
  const onClickSubmit = (data: IFormData): void => {
    console.log(data);
    // data.boardAddress.addressDetail
  };
  return (
    <form onSubmit={wrapFormFunc(handleSubmit(onClickSubmit))}>
      작성자: <input type="text" {...register("writer")} />
{ /* 생성한 yup의 에러메세지는 항상 errors에 담기는데 이 에러는 있을때도 있고 없을 때도 있기 때문에 옵셔널 체이닝을 붙여야 한다. */}      
      <div style={{ color: "red" }}>{formState.errors.writer?.message}</div>
      제목: <input type="text" {...register("title")} />
      <div style={{ color: "red" }}>{formState.errors.title?.message}</div>
      내용: <input type="text" {...register("contents")} />
      <div style={{ color: "red" }}>{formState.errors.contents?.message}</div>
      {/* 주소: <input type="text" {...register("boardAddress.addressDetail")} /> */}
      <button style={{ background: formState.isValid ? "yellow" : "" }}>
        Graphql-API 요청하기
      </button>
    </form>
  );
}

resolver에는 yup이외에도 다른 검증 라이브러리를 사용할 수 있다❗️

  • validation.ts
import * as yup from "yup";
// yup 에러메세지 생성해주기 -> 제어 컴포넌트 형태로 사용해야한다.
export const schema = yup.object({
  writer: yup.string().required("필수입력"),
  // writer: yup.string().min(2,"최소 2자 이상입니다").required("작성자는 필수입력입니다")
  title: yup.string().required("필수입력"),
  contents: yup.string().required("필수입력"),
  // email: yup.string().email("형식 부적합").required("필수입력"),
  // password: yup
  //   .string()
  //   .min(8, "최소 8자리 이상")
  //   .max(15, "최대 15자리 이상")
  //   .required("필수입력"),
  // phone: yup
  //   .string()
  //   .matches(/^\d{3}-\d{3,4}-\d{4}$/, "형식 부적합")
  //   .required("필수입력"),
});

✔️ 공통컴포넌트 구현하기

button과 input이 공통적으로 사용되고 있음으로
컴포넌트 따로 빼주기!

  • index.tsx
import Input01 from "../../../src/components/commons/inputs/01";
import Button01 from "../../../src/components/commons/buttons/01";
export default function GraphqlMutationPage(): JSX.Element {
  const { register, handleSubmit, formState } = useForm<IFormData>({
    resolver: yupResolver(schema),
    mode: "onChange",
  });
  return (
    <form onSubmit={wrapFormFunc(handleSubmit(onClickSubmit))}>
      작성자: <Input01 register={register("writer")} />
      <div style={{ color: "red" }}>{formState.errors.writer?.message}</div>
      제목: <Input01 register={register("title")} />
      <div style={{ color: "red" }}>{formState.errors.title?.message}</div>
      내용: <Input01 register={register("contents")} />
      <div style={{ color: "red" }}>{formState.errors.contents?.message}</div>
      <Button01  title="등록하기" isActive={formState.isValid} />
    </form>
  );
}
  • src/components/commons/inputs
import type { UseFormRegisterReturn } from "react-hook-form";
interface IInputProps {
  type?: "text" | "password";
  register: UseFormRegisterReturn;
}
export default function Input01(props: IInputProps) {
  return <input type={props.type ?? "text"} {...props.register} />;
}
  • src/components/commons/buttons
interface IButtonProps {
  isActive: boolean;
  title: string;
}
export default function Button01(props: IButtonProps): JSX.Element {
  return (
    <button style={{ background: props.isActive ? "yellow" : "" }}>
      {props.title}
    </button>
  );
}

스토리북
공통컴포넌트를 따로 모아놓고 쉽게 볼 수있게 해주는 라이브러리

아니 이렇게 간단한 방법이 있었따니이이이이잉

profile
JUST DO WHATEVER

0개의 댓글