Skip to content

API

は API をシンプルにすることにより、最高な DX を提供することに焦点を当てています。

useForm: Function

useForm を呼び出すことにより、次のメソッドを受け取ることができます。 register, unregister, errors, watch, handleSubmit, reset, setError, clearError, setValue, getValues, triggerValidation, control and formState.

useForm省略可能な引数もあります。 下記の例は、全てのオプションのデフォルト値を示します。

const { register } = useForm({
  mode: 'onSubmit',
  reValidateMode: 'onChange',
  defaultValues: {},
  validationSchema: undefined, // Note: will be deprecated in the next major version with validationResolver
  validationResolver: undefined,
  validationContext: undefined,
  validateCriteriaMode: "firstErrorDetected",
  submitFocusError: true,
  nativeValidation: false, // Note: version 3 only
})
mode: string = 'onSubmit'React Native: only compatible with by using Controller
NameType説明
onSubmit (Default)stringsubmit イベントからバリデーションがトリガーされ、 無効な入力は onChange イベントリスナーをアタッチして再度バリデーションを行います。
onBlurstringblur イベントからバリデーションがトリガーされます。
onChangestring入力の度に change イベントからバリデーションがトリガーされ、複数の再レンダリングが行われます。 非推奨: これをパフォーマンスの悪い習慣と考えてください。
defaultValues: Record<string, any> = {}React Native: Custom register or using Controller

defaultValue/defaultChecked を使用して input のデフォルト値を設定するか (詳細については React ドキュメントを参照) defaultValues を省略可能な引数として渡してフォーム全体のデフォルト値を設定することができます。

重要: defaultValues はカスタムフック内にキャッシュされます。 defaultValues をリセットしたい場合は、 API を使用してください。

注意: defaultValues で定義された値は defaultValue として に注入されます。

注意: 手動で register を適用したフィールドでは React Hook Form に ref を提供しないため、 手動で登録した input (例: register({ name: 'test' })) に defaultValues は自動設定されません。

CodeSandbox
const { register } = useForm({
  defaultValues: {
    firstName: "bill",
    lastName: "luo",
    email: "bluebill1049@hotmail.com",
    pets: [ 'dog', 'cat' ]
  }
})

<input name="firstName" ref={register} /> // ✅ working version
<input name="lastName" ref={() => register({ name: 'lastName' })} />
// ❌ above example does not work with "defaultValues" due to its "ref" not being provided
validationSchema:
Object

スキーマレベルで Yup を使用してフォームバリデーションルールを適用します。 セクションを参照してください。

CodeSandbox
validationResolver:
Function

このコールバック関数を使用すると、任意のスキーマバリデーションまたはカスタムバリデーションを実行できます。 この関数は引数としてフォーム全体の values を持ち、 その値を検証して valueserrors の両方を返す必要があります。詳細については セクションをご覧ください。

validationContext:
Object

このコンテキストオブジェクトは、validationResolver の第二引数または Yup バリデーションのコンテキストオブジェクトに渡されます。

validateCriteriaMode:
firstErrorDetected | all

デフォルトの設定である firstErrorDetected は、全てのフィールドのバリデーションを行い、最初に発生したエラーを収集します。

このオプションを all に設定すると、全てのフィールドのバリデーションが実行され、 発生した全てのエラーが収集されます。

CodeSandbox
reValidateMode:
onChange | onBlur | onSubmit

このオプションを使用すると、エラーのある入力が再度バリデーションされるタイミングを設定することができます。 (デフォルトでは、入力変更時にバリデーションがトリガーされます。) React Native: only compatible with by using Controller

submitFocusError:
boolean = true

デフォルトでは、ユーザーがフォームを送信してそのフォームにエラーが含まれている時、 エラーのある最初のフィールドがフォーカスされます。

注意: ref を持つ登録したフィールドのみが機能します。 手動で登録した input では機能しません。例: register({ name: 'test' }) // doesn't work

register: (Ref, validateRule?) => voidReact Native: Custom register or using Controller

このメソッドを使用すると、input/select の Ref とバリデーションルールを React Hook Form に登録 (register) することができます。

バリデーションルールは全て HTML 標準に基づいており、カスタムバリデーションも可能です。

重要: name 属性は必須かつユニークです。 input の name 属性はドット記法およびブラケット記法もサポートしているため、 ネストされたフォームフィールドを簡単に作成することができます。例は下記の通りです:

Input Nameフォームの送信結果
name="firstName"{ firstName: 'value'}
name="firstName[0]"{ firstName: [ 'value' ] }
name="name.firstName"{ name: { firstName: 'value' } }
name="name.firstName[0]"{ name: { firstName: [ 'value' ] } }

arrays/array フィールドを使用する場合、input の name 属性を name[index] のように割り当てることができます。フィールド配列の例をご覧ください

カスタム登録

また、input を手動で登録 (manual register) することもできます。 これは、カスタムコンポーネントを操作していて Ref にアクセスできない場合に便利です。 React Native や react-select のようなカスタムコンポーネントを使用している場合がこれに該当します。

カスタム登録を使用すると、 input の ref は登録されていないため、 で入力値を更新する必要があります。

register({ name: 'firstName' }, { required: true, min: 8 })

注意: 値の更新中に、カスタム登録した input で再レンダリングをトリガーしたい場合は、 登録した input に type 属性を指定する必要があります。

register({ name: 'firstName', type: 'custom' }, { required: true, min: 8 })

登録オプション

登録オプションを選択すると、下記の API テーブルが更新されます。

Name説明コードの例
ref
React.RefObject
React element ref
<input
  name="test"
  ref={register}
/>
required
boolean
Boolean の値。true の場合、フォームを送信する前に入力値が必須であることを示します。errors オブジェクトにエラーメッセージを返す文字列を割り当てることができます。
<input
  name="test"
  ref={
    register({
      required: true
    })
  }
/>
maxLength
number
input が受け付ける最大文字数。
<input
  name="test"
  ref={
    register({
      maxLength: 2
    })
  }
/>
minLength
number
input が取りうる妥当と判断される最小文字数。
<input
  name="test"
  ref={
    register({
      minLength: 1
    })
  }
/>
max
number
input が受け付ける最大数。
<input
  name="test"
  ref={
    register({
      max: 3
    })
  }
/>
min
number
input が取りうる妥当と判断される最小数。
<input
  name="test"
  ref={
    register({
      min: 3
    })
  }
/>
pattern
RegExp
input の内容が一致する必要がある正規表現。
<input
  name="test"
  ref={
    register({
      pattern: /[A-Za-z]{3}/
    })
  }
/>
validate
Function | Object
引数として、単一のバリデーションを行うためにはコールバック関数を渡すことができ、複数のバリデーションを行うためにはコールバック関数のオブジェクトを渡すことができます。 (例を参照)
// callback function
<input
  name="test"
  ref={
    register({
      validate: value => value === '1'
    })
  }
/>
// object of callback functions
<input
  name="test1"
  ref={
    register({
      validate: {
        positive: value => parseInt(value, 10) > 0,
        lessThanTen: value => parseInt(value, 10) < 10
      }
    })
  }
/>
// you can do asynchronous validation as well
<input
  name="test2"
  ref={
    register({
      validate: async value => await fetch(url)
    })
  }
/>

unregister: (name: string | string[]) => void

このメソッドでは、単一の input または input の配列に unregister を適用することができます。 これは、 useEffect でカスタム登録として input を登録 (register) し、 コンポーネントのアンマウント後に登録を解除する場合に便利です。

注意: input を登録解除 (unregister) すると、 その値は送信されたフォームデータに含まれなくなります。

CodeSandbox
import React from "react"
import { useForm } from "react-hook-form"

export default function App() {
  const { register, handleSubmit, unregister } = useForm();
  const onSubmit = (data) => console.log(data);
  
  useEffect(() => {
    register({ name: 'customRegister' }, { required: true });
    
    return () => unregister('customRegister'); // unregister input after component unmount
  }, [register])

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input type="text" name="firstName" ref={register} />
      <input type="text" name="lastName" ref={register} />
      <button type="button" onClick={() => unregister('lastName')}>unregister</button>
      <input type="submit" />
    </form>
  );
}

errors: Record<string, Object>

オブジェクトには、各 input のフォームのエラーまたはエラーメッセージが含まれています。

注意: V3 と V4 の違い:

  • V4: ネストされたオブジェクト

    理由: Optional chaining はコミュニティの間でより一般的になり、型のサポートが向上するため。

    errors?.yourDetail?.firstName;

  • V3: フラットなオブジェクト

    理由: エラーがシンプルでアクセスしやすいため。

    errors['yourDetail.firstName'];

NameType説明
typestringError Type. eg: required, min, max, minLength
typesRecord<{ string, string | boolean }>これは、単一のフィールドで複数のエラーを返す必要がある、 パスワードのルールのような input のバリデーションに役立ちます。 この機能を有効にするには、 validateCriteriaMode: 'all' を設定してください。
messagestringメッセージはデフォルトでは空文字です。ただし、バリデーションとエラーメッセージで登録するとエラーメッセージが返されます。
refReact.RefObjectinput 要素の参照。
CodeSandbox
import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, errors, handleSubmit } = useForm();
  const onSubmit = data => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input name="singleErrorInput" ref={register({ required: true })} />
      {errors.singleErrorInput && "Your input is required"}

      {/* refer to the type of error to display message accordingly */}
      <input
        name="multipleErrorInput"
        ref={register({ required: true, maxLength: 50 })}
      />
      {errors.multipleErrorInput &&
        errors.multipleErrorInput.type === "required" &&
        "Your input is required"}
      {errors.multipleErrorInput &&
        errors.multipleErrorInput.type === "maxLength" &&
        "Your input exceed maxLength"}

      {/* register with validation */}
      <input type="number" name="numberInput" ref={register({ min: 50 })} />
      {errors.numberInput && "Your input required to be more than 50"}

      {/* register with validation and error message */}
      <input
        name="errorMessage"
        ref={register({ required: "This is required" })}
      />
      {errors.errorMessage && errors.errorMessage.message}
      <input type="submit" />
    </form>
  );
}
CodeSandbox
import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, errors, handleSubmit } = useForm({
    // by setting validateCriteriaMode to 'all', 
    // all validation errors for single field will display at once
    validateCriteriaMode: "all"
  });
  const onSubmit = data => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        type="password"
        name="password"
        ref={register({ required: true, minLength: 10, pattern: /\d+/ })}
      />
      {/* without enter data for the password input will result both messages to appear */}
      {errors.password && errors.password.types.required && (
        <p>password required</p>
      )}
      {errors.password && errors.password.types.minLength && (
        <p>password minLength 10</p>
      )}
      {errors.password && errors.password.types.pattern && (
        <p>password number only</p>
      )}

      <input type="submit" />
    </form>
  );
}

watch: (names?: string | string[] | { nest : boolean }) => any

これは指定された input/inputs を監視し、その値を返します。

  • defaultValue が定義されていない場合、watch の初回のレンダリングは register の前に呼び出されるため undefined を返しますが、 第2引数として defaultValue を設定して値を返すことができます。

  • ただし、引数として useForm defaultValues が初期化された場合、 初回のレンダリングは defaultValues で指定された値を返します。

Type説明Return
stringinput の値を name から監視します (lodash の get 関数に似ています)watch('inputName')
watch('inputName', 'value')
string | string[] | { [key:string] : any } | undefined
string[]複数の input を監視しますwatch(['inputName1'])
watch(['field1'], { field1: '1' })
{ [key:string] : any }
undefined全ての input を監視しますwatch()
watch(undefined, { field: 'value1' })
{ [key:string] : any }
{ nest: boolean }すべての入力を監視し、ネストされたオブジェクトを返しますwatch({ nest: true }){ [key:string] : any }
CodeSandbox
import React from 'react';
import { useForm } from 'react-hook-form';

export default function App(props) {
  const { register, watch } = useForm();
  const watchYes = watch('yes', props.yes); // supply default value as second argument
  const watchAllFields = watch(); // watching every fields in the form
  const watchFields = watch(['yes', 'number']); // target specific fields by their names
  // watch array fields by the key, pet[0] and pet[1] will both be watched and returns values
  const pets = watch('pet'); 
  
  return (
    <form>
      <input name="textInput" ref={register({ required: true, maxLength: 50 })} />
      <input type="checkbox" name="yes" ref={register} />
      <input name="pet[0]" ref={register} />
      <input name="pet[1]" ref={register} />
      
      {watchYes && <input type="number" name="numberInput" ref={register({ min: 50 })} />}
      {/* based on yes selection to display numberInput */}
    </form>
  );
}

handleSubmit: (data: Object, e: Event) => () => void

この関数は、フォームバリデーションに成功するとフォームデータを渡します。また、リモートで呼び出すこともできます。

handleSubmit(onSubmit)()

注意: 非同期バリデーションのための async 関数を渡すことができます。例:

handleSubmit(async (data) => await fetchAPI(data))

CodeSandbox
import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit } = useForm()
  const onSubmit = (data, e) => {
    console.log('Submit event', e)
    alert(JSON.stringify(data))
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input name="firstName" ref={register} />
      <input name="lastName" ref={register} />
      <button type="submit">Submit</button>
    </form>
  )
}

reset: (values?: Record<string, any>, omitResetState: OmitResetState = {}) => void

この関数は、フォーム内のフィールドの値とエラーをリセット (reset) します。omitResetStateを指定することにより、次のことができます。 特定の状態のみをリセットします。 省略可能な引数として values を渡すと、 割り当てられたデフォルト値でフォームをリセットできます。

注意: ref を公開しない React-Select のような制御されたコンポーネントの場合は、 手動で入力値をリセットするために を使用するか、 コンポーネントを使用して制御されたコンポーネントをラップする必要があります。

注意: Controller コンポーネントの値をリセットするには、useFormdefaultValues を指定する必要があります。

CodeSandbox
import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit, reset } = useForm();
  const onSubmit = (data, e) => {
    // e.target.reset(); // HTML standard reset() function will only reset inputs' value
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input name="firstName" ref={register({ required: true })} />
      <input name="lastName" ref={register} />
      <input type="submit" />
      <input type="reset" /> // standard reset button
      <input type="button" onClick={reset} />
      <input type="button" onClick={() => reset({ firstName: "bill" }); }} /> // reset form with values
      <input type="button" onClick={() => {
          reset({
            firstName: "bill"
          }, {
            errors: true, // errors will not be reset 
            dirtyFields: true, // dirtyFields will not be reset
            dirty: true, // dirty will not be reset
            isSubmitted: false,
            touched: false,
            isValid: false,
            submitCount: false,
          });
        }}
      />
    </form>
  );
}
CodeSandbox
import React from "react";
import { useForm, Controller } from "react-hook-form";
import { TextField } from "@material-ui/core";

export default function App() {
  const { register, handleSubmit, reset, setValue, control } = useForm();
  const onSubmit = (data) => { console.log(data) };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller 
        as={TextField} 
        name="firstName"
        control={control} 
        rules={ required: true } 
        defaultValue=""
      />
      <Controller 
        as={TextField} 
        name="lastName"
        control={control}
        defaultValue="" 
      />
      
      <input type="submit" />
      <input type="button" onClick={reset} />
      <input
        type="button"
        onClick={() => {
          reset({
            firstName: "bill",
            lastName: "luo"
          });
        }}
      />
    </form>
  );
}
CodeSandbox
import React, { useEffect } from "react";
import { useForm } from "./src";

const defaultValues = {
  firstName: "bill",
  lastName: "luo"
};

export default function App() {
  const { register, reset, watch, setValue } = useForm({
    defaultValues
  });
  const values = watch();

  useEffect(() => {
    register({ name: "firstName" }, { required: true });
    register({ name: "lastName" });
  }, [register]);

  return (
    <form>
      <input
        name="firstName"
        onChange={e => setValue("firstName", e.target.value)}
        value={values.firstName}
        placeholder="First Name"
      />
      <input
        name="lastName"
        onChange={e => setValue("lastName", e.target.value)}
        value={values.lastName}
        placeholder="Last Name"
      />
      <button
        type="button"
        onClick={() => {
          reset(defaultValues);
        }}
      >
        Reset
      </button>
    </form>
  );
}

setError:
(name: string | ManualFieldError[], type?: string | Object, message?: string) => void

単一または複数の input のエラーを手動で設定できます。

注意: このメソッドはエラーを保存せず、フォームの送信をブロックしません。 非同期バリデーション後にユーザーへエラーをフィードバックしたい場合は、 handleSubmit 関数内で使用してください。

CodeSandbox
import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, errors, setError } = useForm()

  return (
    <form>
      <input
        name="username"
        onChange={e => {
          const value = e.target.value
          // this will clear error by only pass the name of field
          if (value === "bill") return clearError("username")
          // set an error with type and message
          setError("username", "notMatch", "please choose a different username")
        }}
        ref={register}
      />
      {errors.username && errors.username.message}
    </form>
  )
}
CodeSandbox
import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, errors, setError } = useForm()

  return (
    <form>
      <input name="username" ref={register} />
      {errors.username && errors.username.message}
      
      <input name="lastName" ref={register} />
      {errors.lastName && errors.lastName.message}
      
      <button type="button" onClick={() => {
        setError([
          {
            type: 'required',
            name: 'lastName',
            message: 'This is required.',
          },
          {
            type: 'minLength',
            name: 'username',
            message: 'Minlength is 10',
          },
        ]);
      }}>
        Set Errors for a single field
      </button>
    </form>
  )
}
CodeSandbox
import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, setError } = useForm({
    validateCriteriaMode: "all" // you will need to enable validate all criteria mode
  });

  return (
    <form>
      <input name="username" ref={register} />
      {errors.username && errors.username.types && (
        <p>{errors.username.types.required}</p>
      )}
      {errors.username && errors.username.types && (
        <p>{errors.username.types.minLength}</p>
      )}

      <button
        type="button"
        onClick={() =>
          setError("username", {
            required: "This is required",
            minLength: "This is minLength"
          })
        }
      >
        Trigger
      </button>
    </form>
  );
}

clearError: (name?: string | string[]) => void

  • undefined: 全てのエラーをリセット

  • string: 単一のエラーをリセット

  • string[]: 複数のエラーをリセット

import React from "react";
import { useForm } from "react-hook-form";

export default () => {
  const { clearError, errors, register } = useForm();

  return (
    <form>
      <input name="firstName" ref={register({ required: true })} />
      {errors.firstName && "This is required"}
      <input name="lastName" ref={register({ required: true })} />
      {errors.lastName && "This is required"}

      <button type="button" onClick={() => clearError("firstName")}>
        Clear
      </button>
      <button
        type="button"
        onClick={() => clearError(["firstName", "lastName"])}
      >
        Clear Multiple
      </button>
      <button type="button" onClick={() => clearError()}>
        Clear All
      </button>
    </form>
  );
};

setValue:

(name: string, value: any, shouldValidate?: boolean) => void
(Record<Name, any>[], shouldValidate?: boolean) => void

この関数を使用すると、input/select の値を動的に設定できます。 setValue は不要な再レンダリングを避けようとしますが、 以下の条件でのみ再レンダリングをトリガーします。

  • 値の更新によってエラーがトリガーされるとき

  • 値の更新によってエラーが修正されるとき

  • setValue が初めて実行され、 formState の dirty が true に設定されたとき

  • setValue が実行され、 formState の touched が更新されたとき

注意: このメソッドを呼び出すことで、formState は input の name touched にプッシュします。

shouldValidatetrue に設定すると、 フィールドのバリデーションがトリガーされます。 例: setValue('name', 'value', true)

CodeSandbox
import React from "react"
import { useForm } from "react-hook-form"

export default function App() {
  const { register, setValue } = useForm()

  return (
    <form>
      <input name="test" ref={register} />
      <input name="test1" ref={register} />
      <input name="object.firstName" ref={register} />
      <input name="array[0].firstName" ref={register} />
      <button type="button" onClick={() => {
        // manually set the 'test' field with value 'bill'
        setValue('test', 'bill')
        
        // set multiple values
        setValue([
          { test : '1', },
          { test1 : '2', },
        ])
        
        // set value as object or array
        setValue('object', { firstName: 'test' })
        setValue('array', [{ firstName: 'test' }])
      }}>SetValue</button>
    </form>
  )
}

getValues: (payload?: { nest: boolean }) => Object

この関数は、フォーム全体のデータを返します。

  • デフォルトでは、getValues() はフォームデータをフラットな構造で返します。 例: { test: 'data', test1: 'data1'}

  • 定義されたフォームフィールドで、getValues({ nest: true }) は input の name 属性に基づいてネストされた構造でデータを返します。 例: { test: [1, 2], test1: { data: '23' } }

CodeSandbox
import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, getValues } = useForm()

  return (
    <form>
      <input name="test" ref={register} />
      <input name="test1" ref={register} />

      <button
        type="button"
        onClick={() => {
          const values = getValues()
          // you can run auto save function here eg: autoSave(values)
        }}
      >
        Get Values
      </button>
    </form>
  );
}

triggerValidation: (payload?: string | string[]) => Promise<boolean>

フォームで input/select のバリデーションを手動でトリガーします。

注意: バリデーションが失敗すると、errors オブジェクトが更新されます。

CodeSandbox
import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, triggerValidation, errors } = useForm();
  console.log(errors);

  return (
    <form>
      <input name="firstName" ref={register({ required: true })} />
      <input name="lastName" ref={register({ required: true })} />
      <button type="button" onClick={() => { triggerValidation("lastName"); }}>Trigger</button>
      <button type="button" onClick={() => { triggerValidation(["firstName", "lastName"]); }}>Trigger Multiple</button>
      <button type="button" onClick={() => { triggerValidation(); }}>Trigger All</button>
      <button
        type="button"
        onClick={async () => {
          const result = await triggerValidation("lastName");
          if (result) { console.log('valid input') }
        }}
      >
        Trigger with result
      </button>
    </form>
  );
}

control: Object

このオブジェクトは、 React Hook Form の Controller コンポーネント用に作成され、 React Hook Form に制御されたコンポーネントを登録するためのメソッドが含まれています。

CodeSandbox
import React from "react";
import { useForm, Controller } from "react-hook-form";
import { TextField } from "@material-ui/core";

function App() {
  const { control, handleSubmit } = useForm();

  const onSubmit = data => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        as={TextField}
        name="firstName"
        control={control}
        defaultValue=""
      />
      
      <input type="submit" />
    </form>
  );
}

formState: Object

このオブジェクトには、フォームの状態に関する情報が含まれています。

重要: formState はレンダリングパフォーマンスの改善のために Proxy にラップされているので、状態の更新を有効にするには、render 前に formState を呼び出すか、読み込む必要があります。

NameType説明
dirtybooleanユーザが入力操作した後 true に設定します。
dirtyFieldsSetユーザーが変更したフィールドの一意の Set オブジェクト。
isSubmittedbooleanユーザーがフォームを送信した後 true に設定します。
touchedobject操作された全ての input の name の配列。
isSubmittingbooleanフォームの送信中は true に設定し、 フォームの送信後は false に設定します。
submitCountnumberフォームの送信回数。
isValidboolean
エラーがない場合は true に設定します。

Note: isValid is affected by mode. This state is only applicable with onChange and onBlur mode.

CodeSandbox

Controller: Component

React Hook Form は、非制御コンポーネントとネイティブ HTML input をサポートしていますが、 React-Select AntD Material-UIなどの外部の制御された UI コンポーネントライブラリと組み合わせての使用​​を避けることは難しいです。 このラッパーコンポーネントにより、制御されたコンポーネントと組み合わせて簡単に使用​​できるようになります。

Controllerコンポーネントへ渡す全ての props は、as prop で指定した Component インスタンスに転送されます。 つまり、label prop を必要とするカスタム Switch コンポーネントがあるとします。 この label prop を Controller コンポーネントに直接渡すことができます。name prop は、主に後でフォームから値にアクセスするために使用されます。

defaultValue prop を使用する場合、useForm で設定した defaultValues の値より優先されます。

NameType必須説明
namestringinput のユニークな name 。
asReact.ElementType | string制御されたコンポーネント。 例: as="input" または as={<TextInput />}
controlObjectcontrol オブジェクトは useForm から呼び出されます。 ただし、 FormContext を使用している場合は省略できます。
defaultValueany非制御コンポーネントの defaultValue と同じですが、 boolean 値を指定すると、チェックボックスの input として扱われます。

注意: useFormdefaultValue または defaultValues のどちらかを指定する必要があります。

注意: 指定した場合、これは useForm defaultValue よりも優先されます。

注意: フォーム内でデフォルト値を引数として reset を呼び出す場合、 インラインの defaultValue を設定する代わりに、 useForm で defaultValues を指定する必要があります。

rulesObjectregister によるバリデーションルール。
onChange(args: any | EventTarget) => anyこの prop を使用すると、戻り値をカスタマイズすることができます。 外部 UI コンポーネントの value prop の形状を確認してください。 ペイロードの形状が type 属性を含むオブジェクトの場合、value または checked 属性が読み込まれます。
onChange={{([ event ]) => event.target.value}}
onChange={{([ { checked } ]) => ({ checked })}}
onChangeNamestringこの prop を使用すると、特定のイベント名をターゲットにすることができます。 例えば、 onChange イベントが onTextChange と命名されている場合。
onBlurNamestringこの prop を使用すると、特定のイベント名をターゲットにすることができます。 例えば、 onBlur イベントが onTextBlur と命名されている場合。
valueNamestringこの prop を使用すると、value prop をオーバーライドし、value prop を使用しない他のコンポーネントをサポートできます。 例えば、 checked, selected 等...
CodeSandbox
import React from 'react';
import Select from 'react-select';
import { TextField } from "@material-ui/core";
import { useForm, Controller } from 'react-hook-form';

const options = [
  { value: 'chocolate', label: 'Chocolate' },
  { value: 'strawberry', label: 'Strawberry' },
  { value: 'vanilla', label: 'Vanilla' },
];

function App() {
  const { handleSubmit, control } = useForm();

  return (
    <form onSubmit={handleSubmit(data => console.log(data))}>
      {* // Preferred syntax on most cases. If you need props, pass TextField props to Controller props (forwarded) *}
      <Controller as={TextField} name="TextField" control={control} defaultValue="" />
      
      {* // Another possibility, any potential props passed to <Checkbox/> will be overrided. SomeName => Checkbox *}
      <Controller
        as={<Select options={options} />}
        control={control}
        rules={{ required: true }}
        onChange={([selected]) => {
          // Place your logic here
          return selected;
        }}
        name="reactSelect"
        defaultValue={{ value: 'chocolate' }}
      />
      
      <button>submit</button>
    </form>
  );
}
CodeSandbox
import React from "react";
import { Text, View, TextInput, Button, Alert } from "react-native";
import { useForm, Controller } from "react-hook-form";

export default function App() {
  const { control, handleSubmit, errors } = useForm();
  const onSubmit = data => Alert.alert(
    "Form Data",
    JSON.stringify(data),
  );

  return (
    <View>
      <Text>First name</Text>
      <Controller
        as={TextInput}
        control={control}
        name="firstName"
        onChange={args => args[0].nativeEvent.text}
        rules={{ required: true }}
        defaultValue=""
      />
      {errors.firstName && <Text>This is required.</Text>}

      <Text>Last name</Text>
      <Controller
        as={TextInput}
        control={control}
        name="lastName"
        onChange={args => args[0].nativeEvent.text}
        defaultValue=""
      />


      <Button title="Submit" onPress={handleSubmit(onSubmit)} />
    </View>
  );
}

ErrorMessage: Component

関連する input のエラーメッセージを表示するためのシンプルなコンポーネント。

NameType必須説明
namestring関連するフィールド名
errorsobjectReact Hook Form の errors オブジェクト
messagestringインラインエラーメッセージ。
asReact.ElementType | stringラッパーコンポーネント、または HTML タグ。 例: as="span" または as={<Text />}
children({ message: string, messages?: string[]}) => anyこれは、単一または複数のエラーメッセージをレンダリングするための render prop です。

注意: messages を使用するためには、 validateCriteriaMode を 'all' に設定する必要があります。

CodeSandbox
import React from "react";
import { useForm, ErrorMessage } from "react-hook-form";

export default function App() {
  const { register, errors, handleSubmit } = useForm();
  const onSubmit = data => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input name="singleErrorInput" ref={register({ required: 'This is required.' })} />
      <ErrorMessage errors={errors} name="singleErrorInput" />
      
      <ErrorMessage errors={errors} name="singleErrorInput">
        {({ message }) => <p>{message}</p>}
      </ErrorMessage>
      
      <input name="name" ref={register({ required: true })} />
      <ErrorMessage errors={errors} name="name" message="This is required" />
      
      <input type="submit" />
    </form>
  );
}
CodeSandbox
import React from "react";
import { useForm, ErrorMessage } from "react-hook-form";

export default function App() {
  const { register, errors, handleSubmit } = useForm({
    validateCriteriaMode: "all"
  });
  const onSubmit = data => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        name="multipleErrorInput"
        ref={register({
          required: "This is required.",
          pattern: {
            value: /d+/,
            message: "This input is number only."
          },
          maxLength: {
            value: 10,
            message: "This input exceed maxLength."
          }
        })}
      />
      <ErrorMessage errors={errors} name="multipleErrorInput">
        {({ messages }) =>
          messages &&
          Object.entries(messages).map(([type, message]) => (
            <p key={type}>{message}</p>
          ))
        }
      </ErrorMessage>

      <input type="submit" />
    </form>
  );
}

useFormContext: Component

フォームコンテキストは、コンポーネントツリーに深くネストされた input があり、 メソッドを props として深く渡すことが苦痛になる場合の問題を解決することを目的としています。

NameType説明
...propsObjectAccept all useForm methods.

フォームが FormContext でラップされると、 ラップされた子コンポーネントで useFormContext を使用して function を呼び出すことができます。

注意: useFormContext を呼び出すと全ての useForm フック関数が得られます。

const methods = useFormContext() // methods contain all useForm functions
CodeSandbox
import React from "react"
import { useForm, FormContext, useFormContext } from "react-hook-form"

export default function App() {
  const methods = useForm()
  const onSubmit = data => { console.log(data) }

  return (
    <FormContext {...methods} > // pass all methods into the context
      <form onSubmit={methods.handleSubmit(onSubmit)}>
        <NestedInput />
        <input type="submit" />
      </form>
    </FormContext>
  )
}

function NestedInput() {
  const { register } = useFormContext() // retrieve all hook methods
  return <input name="test" ref={register} />
}

useFieldArray: ({ control?: any, name: string, keyName?: string = 'id' }) => object

フィールド配列(動的な複数の input)を操作するためのカスタムフック。 このフックの背後にある動機は、より良いユーザーエクスペリエンスとフォームのパフォーマンスを提供することです。この短いビデオで、制御されたフィールド配列と非制御フィールド配列を比較できます。

このフックは、次のオブジェクトと関数を提供します。

function Test() {
  const { control, register } = useForm();
  const { fields, append, prepend, remove, swap, move, insert } = useFieldArray(
    {
      control, // control props comes from useForm (optional: if you are using FormContext)
      name: "test", // unique name for your Field Array
      // keyName: 'id', default to "id", you can change the key name
    }
  );

  return (
    {fields.map((field, index) => (
      {/* important: using id from to track item added or removed */}
      <div key={field.id}>
        <input name={`test[${index}]`} ref={register} />
      </div>
    ))}
  );
}

重要: useFieldArray は非制御コンポーネントに基づいて構築されます。 下記の注意事項は、実装時の動作を理解し、注意するのに役立ちます。

  • useForm フックで defaultValues を指定することにより、 fields 配列に値を格納することができます。

  • fields オブジェクトから id をコンポーネントの key に割り当てていることを確認してください。

  • デフォルト値を設定するか、入力値をリセットしたい場合は、defaultValue を設定します。

  • 次々とアクションを呼び出すことはできません。アクションはレンダリングごとにトリガーする必要があります。

    // ❌ The following is not correct
    handleChange={() => {
      if (fields.length === 2) {
        remove(0);
      }
      append({ test: 'test' });
    }}
    
    // ✅ The following is correct and second action is triggered after next render
    handleChange={() => {
      append({ test: 'test' });
    }}
    
    React.useEffect(() => {
      if (fields.length === 2) {
        remove(0);
      }
    }, fields)
                
  • useFormContext を使用する際には、ref={register} ではなく ref={register()} を適用して、 map 中に register が呼び出されるようにすることが重要です。

  • useEffectのカスタムレジスタでは機能しません。
NameType説明
fieldsobject & { id: string }このオブジェクトは、input をマップおよびレンダリングするための信頼できる情報源です。

重要: 各 input は制御することができないため、 マップされたコンポーネントには id が必須です。 これは、React が変更、追加もしくは削除されたのかを識別するのに役立ちます。

eg: {fields.map(d => <input key={d.id} />)}

append(obj: object | object[]) => voidフィールドの最後に input を追加します。
prepend(obj: object | object[]) => voidフィールドの先頭に input を追加します。
insert(index: number, value: object) => void特定の位置に input を挿入します。
swap(from: number, to: number) => voidinput の位置を入れ替えます。
move(from: number, to: number) => voidinput を別の位置に移動します。

注意: move swap の違いは、move を呼び出し続けると input が円を描いて押し込まれるのに対して、swap は2つの input の位置を変更するだけです。

remove(index?: number | number[]) => void特定の位置の input を削除します。引数で index を渡さない場合は全ての input を削除します。
CodeSandbox
import React from "react";
import { useForm, useFieldArray } from "react-hook-form";

function App() {
  const { register, control, handleSubmit } = useForm({
    // defaultValues: {}; you can populate the fields by this attribute 
  });
  const { fields, append, prepend, remove } = useFieldArray({
    control,
    name: "test"
  });
  return (
    <form onSubmit={handleSubmit(data => console.log("data", data))}>
      <ul>
        {fields.map((item, index) => (
          <li key={item.id}>
            <input name={`test[${index}].name`} ref={register} /> 
            <button onClick={() => remove(index)}>Delete</button>
          </li>
        ))}
      </ul>
      <section>
        <button type="button" onClick={() => append({ name: "test" })} >
          append
        </button>
        <button type="button" onClick={() => prepend({ name: "test1" })}>
          prepend
        </button>
      </section>
    </form>
  );
}

validationResolver: (values: any, validationContext?: object) => object

この関数を使用すると、JoiSuperstruct などの任意の外部のバリデーションメソッドを実行できます。 実際には、Yup を外部の(スキーマ)バリデーションライブラリとして制限するだけがゴールではありません。 私たちは React Hook Form で動作する多くのバリデーションライブラリをサポートしたいと思っています。 カスタムバリデーションロジックを作成して検証することもできます。

注意: values errors を含むオブジェクトを返していることを確認してください。 デフォルト値は空のオブジェクト {} である必要があります。

注意: 返す errors オブジェクトのキーは、フォーム内の input(name属性)に関連させる必要があります。

注意: この関数は validationSchema と同様にカスタムフック内にキャッシュされますが、 validationContext は再レンダリングのたびに変更できるミュータブルなオブジェクトです。

注意: ライブラリ自体が特定のフィールドに対してエラーオブジェクトを評価し、 それに応じて再レンダリングをトリガーするため、ユーザーの入力中、一度に一つのフィールドでのみ input の再検証が発生します。

CodeSandbox
import React from "react";
import { useForm } from "react-hook-form";
import Joi from "@hapi/joi";

const validationSchema = Joi.object({
  username: Joi.string().required()
});

const resolver = (data: any, validationContext) => {
  const { error, value: values } = validationSchema.validate(data, {
    abortEarly: false
  });

  return {
    values: error ? {} : values,
    errors: error
      ? error.details.reduce((previous, currentError) => {
          return {
            ...previous,
            [currentError.path[0]]: currentError
          };
        }, {})
      : {}
  };
};

export default function App() {
  const { register, handleSubmit, errors } = useForm({
    validationResolver: resolver,
    validationContext: { test: "test" }
  });

  return (
    <form onSubmit={handleSubmit(d => console.log(d))}>
      <input type="text" name="username" ref={register} />
      <input type="submit" />
    </form>
  );
}

validationSchema: Object

外部バリデーションスキーマでバリデーションルールを一元管理したい場合は、 省略可能な引数として useForm validationSchema を適用できます。 React Hook Form は現在、オブジェクトスキーマバリデーションで Yup をサポートしています。

CodeSandbox
import React from 'react'
import ReactDOM from 'react-dom'
import { useForm } from 'react-hook-form'
import * as yup from 'yup'

const SignupSchema = yup.object().shape({
  name: yup.string().required(),
  age: yup.number().required(),
})

export default function App() {
  const { register, handleSubmit, errors } = useForm({
    validationSchema: SignupSchema
  })
  const onSubmit = data => { console.log(data); }
  console.log(errors)

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input name="name" ref={register} />
      <input type="number" name="age" ref={register} />
      <input type="submit" />
    </form>
  )
}

Browser built-in validation (V3 only)

下記の例は、ブラウザバリデーションを活用する方法を示しています。nativeValidationtrue に設定するだけで、 残りの構文は標準のバリデーションと同じになります。

注意: この機能は使用率が低いため V4 で削除されましたが、 V3 では引き続き使用できます。

CodeSandbox
import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit } = useForm({ nativeValidation: true });
  const onSubmit = async data => { alert(JSON.stringify(data)); };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        name="firstName"
        ref={register({ required: "Please enter your first name." })} // custom message
      />
      <input name="lastName" ref={register({ required: true })} />
      <input type="submit" />
    </form>
  );
}

高度な使用法

React Hook Form を使用して、複雑でアクセス可能なフォームを構築する方法を学びます。