React Hook Form, Compound Components 및 Zod를 사용하여 구성 가능한 양식을 만드는 방법

15505 단어 hookzodreacttypescript
이 기사에서는 고급 React 개념을 사용하여 재사용 가능한 구성 요소, 유효성 검사가 있는 양식을 만들고 구성 요소 간에 데이터를 공유하는 방법을 보여줍니다. 이렇게 하면 양식 작성을 허용하면서 소품 드릴링 및 컨텍스트 남용을 피할 수 있습니다. Typescript로 유효할 수 있는 만큼만 가능합니다.

복합 구성 요소



첫 번째 복합 구성 요소는 구성 요소 간에 부모-자식 관계가 있음을 독자에게 설명하는 방법입니다. 자식을 정의하기 전에 부모를 정의해야 합니다. There's a whole article about that on Smashing Magasine . 기본적으로 입력을 사용하기 전에 양식 구성 요소를 만들어야 한다는 것을 알고 있는 아래와 같은 구성 요소를 가질 수 있습니다. 독자는 이러한 구성 요소가 재사용 가능하다는 것을 추론할 수도 있습니다.

<Form onSubmit={onSubmit}>
  <Form.Input name="firstName" label="First name" />
  <Form.Input name="lastName" label="Last name" />
  <Form.Submit type="button"/>
</Form>


재사용 가능한 구성 요소로 양식 작성



폼을 재사용 가능하게 만들려면 재사용 가능한 구성 요소를 만들어야 하며 필요에 따라 폼을 작성할 수 있어야 합니다. For this React Hook Form provides a small example . 여기 스크린샷이 있습니다.


그러나이 솔루션에는 문제가 있습니다. register 함수를 전달하는 모든 하위 구성 요소를 생성하므로 모든 하위 구성 요소가 HTML 입력 또는 선택이어야 합니다.



문서에서 다른 API를 사용하여 이를 우회할 수 있습니다.

양식 컨텍스트 사용



form context을 사용하면 깊이에 관계없이 하위 구성 요소를 만들 수 있습니다. 모든 메소드를 전달하는 <FormProvider>로 양식을 래핑합니다.

export function Form({
  schema,
  onSubmit,
  children,
  defaultValues
}: {
  schema: any
  onSubmit: (data: Record<string, any>, event?: React.BaseSyntheticEvent) => void
  children: any
  defaultValues?: Record<string, any>
}) {
  const methods = useForm({
    defaultValues,
    resolver: zodResolver(schema)
  })
  const handleSubmit = methods.handleSubmit

  return (
    <FormProvider {...methods}>
      <form onSubmit={handleSubmit(onSubmit)}>
        {children}
      </form>
    </FormProvider>
  )
}


이제 우리는 입력을 React Hook Form과 <Input>register와 같은 다른 상태에 연결하는 데 필요한 errors 함수를 얻는 아래와 같이 정의된 isSubmitting를 가질 수 있습니다. 이 오류 처리는 구성 요소 내에서 이루어지며 제출할 때 입력이 잠깁니다.

Form.Input = function Input({
  name,
  displayName,
  type
}: {
  name: string
  displayName: string
  type: string
}) {
  const {
    register,
    formState: { isSubmitting, errors }
  } = useFormContext()

  return (
    <div>
      <label className="block">
        <span className="block">{displayName}</span>
        <input
          type={type}
          {...register(name)}
          disabled={isSubmitting}
        />
      </label>
      {errors[name as string] && (
        <p className="error">{errors[name as string]?.message}</p>
      )}
    </div>
  )
}


유효성 검사를 위한 스키마 할당



이 양식이 재사용 가능하고 유효하려면 입력에 대한 유효성 검사를 수행해야 합니다. React Hook Form은 간단한 유효성 검사를 제공하지만 여기서는 스키마 유효성 검사로 zod을 사용합니다. 이렇게 하면 양식이 더 복잡한 유효성 검사를 처리할 준비가 됩니다.
유효성 검사 스키마를 Form 구성 요소에 전달하여 유효성 검사를 추가할 수 있습니다.

+ import { zodResolver } from "@hookform/resolvers/zod"
...
function Form({
+ schema,
...
}: {
+ schema: any
...
}
  const methods = useForm({
    defaultValues,
+    resolver: zodResolver(schema)
  })



export const FormSchema = z.object({
  email: z.string().email(),
  username: z.string().min(3, { message: "Must be more than 3 characters" }),
  pizzaChoice: z.string(),
  accept: z.literal(true, {
    errorMap: () => ({
      message: "You must accept Terms and Conditions."
    })
  }),
  tier: z
    .string({ invalid_type_error: "Please select a payment tier." })
    .refine((val) => Tiers.map((tier) => tier.id).includes(val))
})

<Form schema={FormSchema} onSubmit={onSubmit} defaultValues={someInitialValues}>
...
</Form>


Typescript 유효성 검사를 사용한 라이브 예제



유효한 Typescript가 포함된 라이브 예제가 있고 이름 속성은 스키마의 키 중 하나여야 합니다.


You can find the live example here

좋은 웹페이지 즐겨찾기