Caroa UI

Form

react-hook-formと連携したフォームコンポーネント。

インポート

react-hook-form依存のため、専用エントリポイント /form からインポートします(FormはServer Componentsで使えないためrootからは意図的に除外されています)。

'use client'
 
import { useForm } from 'react-hook-form'
import {
  Form,
  FormField,
  FormItem,
  FormLabel,
  FormControl,
  FormDescription,
  FormMessage,
} from '@caroainc/ui-components/form'
import { Input } from '@caroainc/ui-components/server'
import { Button } from '@caroainc/ui-components/server'

基本的な使い方

interface FormData {
  email: string
  password: string
}
 
function LoginForm() {
  const form = useForm<FormData>()
 
  const onSubmit = (data: FormData) => {
    console.log(data)
  }
 
  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
        <FormField
          control={form.control}
          name="email"
          render={({ field }) => (
            <FormItem>
              <FormLabel>メールアドレス</FormLabel>
              <FormControl>
                <Input type="email" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <FormField
          control={form.control}
          name="password"
          render={({ field }) => (
            <FormItem>
              <FormLabel>パスワード</FormLabel>
              <FormControl>
                <Input type="password" {...field} />
              </FormControl>
              <FormDescription>8文字以上で入力してください</FormDescription>
              <FormMessage />
            </FormItem>
          )}
        />
        <Button type="submit">ログイン</Button>
      </form>
    </Form>
  )
}

バリデーション付き

import { zodResolver } from '@hookform/resolvers/zod'
import * as z from 'zod'
 
const schema = z.object({
  email: z.string().email('有効なメールアドレスを入力してください'),
  password: z.string().min(8, '8文字以上で入力してください'),
})
 
const form = useForm({
  resolver: zodResolver(schema),
})

サブコンポーネント

コンポーネント役割
Formreact-hook-formFormProviderそのもの
FormFieldControllerのラッパー。nameをcontextで配下に共有する
useFormFieldFormField配下で使う内部フック。iderror・各要素のid(formItemId等)を返す
FormItem1フィールド分のラッパー(React.useId()でid採番)
FormLabelラベル。エラー時にdata-errorが付き赤字になる。htmlForは自動配線される
FormControl実際の入力要素(Input等)をSlot合成し、idaria-describedbyaria-invalidを自動配線する
FormDescription説明文。idが自動配線されaria-describedbyから参照される
FormMessageエラーメッセージ。errorがあればそれを表示し、無ければchildrenを表示。両方無ければ描画されない

Props (FormField)

PropTypeDefaultDescription
control*Control-react-hook-formのcontrol
name*string-フィールド名
render*(props) => ReactNode-フィールドのレンダリング関数

Props (FormItem / FormLabel / FormControl / FormDescription / FormMessage)

PropTypeDefaultDescription
classNamestring-追加のCSSクラス(全サブコンポーネント共通)
childrenReactNode-FormMessageの場合、react-hook-formのエラーが無いときのみ表示される

react-hook-formを使わない単純なフォームレイアウトが必要な場合は、react-hook-form非依存の Field コンポーネント群も利用できます。

On this page