---
title: "TanStack Formとは？使い方とReact Hook Formとの違い・v2 alphaの変更点【v1.33】"
url: "https://www.issoh.co.jp/tech/details/6350/"
published: 2025-04-17
updated: 2026-11-04
categories: ["React"]
publisher: "株式会社一創"
---

# TanStack Formとは？使い方とReact Hook Formとの違い・v2 alphaの変更点【v1.33】

TanStack Formは、TanStack Query・TanStack Router・TanStack Startと同じTanStackが開発しているフォーム状態管理ライブラリです。UIを持たないヘッドレス設計で、フィールド名や値の型をTypeScriptが推論します。2026年11月4日時点の安定版は`@tanstack/react-form` 1.33.5で、作り直された次期版v2が`2.0.0-alpha.3`として公開されています。この記事では1.33.5と2.0.0-alpha.3をReact 19・zod 4.6.7・yup 1.7.1と組み合わせて型検査と実行を行い、導入手順、検証の落とし穴、React Hook Formとの選び分け、v2で変わる書き方を整理します。

## まとめ：TanStack Formの導入と選定の要点

- **パッケージ**：Reactなら`npm install @tanstack/react-form`。`@tanstack/form`という名前のパッケージはありません。1系はReact 17・18・19に対応します。
- **版**：本番で使うのは1.33.5（2026年8月11日）。v2は2026年10月23日の`2.0.0-alpha.3`が最新で、検証の書き方と描画の参照先が変わります。
- **スキーマ検証**：zod・valibot・ArkTypeはスキーマを`validators`にそのまま渡せます。yupは同期の`onBlur`に渡すと例外になるため`onBlurAsync`に渡します。
- **エラー表示**：スキーマ由来のエラーはオブジェクトです。`errors.join(',')`ではなく`err?.message`を表示します。
- **React Hook Formとの違い**：入力は`field.state.value`と`handleChange`で結ぶ制御型で、Vue・Angular・Solid・Svelte・Litでも同じ設定で書けます。React専用で書く量を減らしたいならReact Hook Formが手軽で、`useForm`単体のgzip実測も約5KB小さい値でした。

## TanStack Formの現在の版とパッケージ構成

npmの公開履歴では、初版0.0.1が2023年4月25日、1.0.0が2025年3月2日です。1系はその後小刻みに更新され、2026年8月11日の1.33.5が`latest`のまま約3か月続いています。開発の中心はv2へ移っており、`alpha`タグには2026年8月10日から10月23日までに4つの版が出ました。リポジトリはMITライセンスで、GitHubのスター数は6,762（2026年11月4日）です。

| 用途           | パッケージ                           | latest | alpha         |
| ------------ | ------------------------------- | ------ | ------------- |
| React        | `@tanstack/react-form`          | 1.33.5 | 2.0.0-alpha.3 |
| Vue          | `@tanstack/vue-form`            | 1.33.5 | 2.0.0-alpha.3 |
| Angular      | `@tanstack/angular-form`        | 1.33.5 | 2.0.0-alpha.3 |
| Solid・Svelte | `@tanstack/solid-form`ほか        | 1.33.5 | 2.0.0-alpha.3 |
| Lit          | `@tanstack/lit-form`            | 1.25.5 | 2.0.0-alpha.3 |
| Next.js連携    | `@tanstack/react-form-nextjs`   | 1.33.5 | 2.0.0-alpha.3 |
| Devtools     | `@tanstack/react-form-devtools` | 0.2.34 | 1.0.0-alpha.3 |

フレームワーク非依存のロジックは`@tanstack/form-core`にあり、各アダプタはその上に乗っています。サーバーの取得結果を初期値に使う構成では[TanStack Query](/tech/details/10307/)と、画面遷移と型をそろえる構成では[TanStack Router](/tech/details/9913/)と組み合わせるのが一般的です。

## @tanstack/react-formのインストールと最小のフォーム

インストールは1行です。依存として`@tanstack/form-core`と`@tanstack/react-store`が入り、スキーマ検証に使うライブラリは別に入れます。

```
npm install @tanstack/react-form@1.33.5 zod@4.6.7
```

次のコードは、メールアドレスとパスワードを持つ登録フォームです。tsc 7.0.2の`strict`で型エラーなしを確認しています。

```
import { useForm } from '@tanstack/react-form'
import { z } from 'zod'

const signupSchema = z.object({
  email: z.string().email('メールアドレスの形式で入力してください'),
  password: z.string().min(8, '8文字以上で入力してください'),
})

export function SignupForm() {
  const form = useForm({
    defaultValues: { email: '', password: '' },
    validators: { onChange: signupSchema },
    onSubmit: async ({ value }) => {
      await fetch('/api/signup', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(value),
      })
    },
  })

  return (
    <form
      onSubmit={(e) => {
        e.preventDefault()
        e.stopPropagation()
        form.handleSubmit()
      }}
    >
      <form.Field name="email">
        {(field) => (
          <div>
            <label htmlFor={field.name}>メール</label>
            <input
              id={field.name}
              name={field.name}
              value={field.state.value}
              onBlur={field.handleBlur}
              onChange={(e) => field.handleChange(e.target.value)}
            />
            {field.state.meta.isTouched &&
              field.state.meta.errors.map((err) => (
                <p key={err?.message} role="alert">{err?.message}</p>
              ))}
          </div>
        )}
      </form.Field>
      <form.Field name="password">
        {(field) => (
          <div>
            <label htmlFor={field.name}>パスワード</label>
            <input
              id={field.name}
              type="password"
              value={field.state.value}
              onBlur={field.handleBlur}
              onChange={(e) => field.handleChange(e.target.value)}
            />
            {field.state.meta.isTouched &&
              field.state.meta.errors.map((err) => (
                <p key={err?.message} role="alert">{err?.message}</p>
              ))}
          </div>
        )}
      </form.Field>
      <form.Subscribe selector={(state) => [state.canSubmit, state.isSubmitting]}>
        {([canSubmit, isSubmitting]) => (
          <button type="submit" disabled={!canSubmit}>
            {isSubmitting ? '送信中…' : '登録する'}
          </button>
        )}
      </form.Subscribe>
    </form>
  )
}
```

読み方の要点は4つです。

- `<form.Field name="email">`の子に関数を渡し、`field.state.value`と`field.handleChange`を入力要素へ自分で結びます。`register`や`getInputProps`のような「propsをまとめて返す関数」はありません。
- `form.handleSubmit()`は送信イベントを止めないため、`e.preventDefault()`を先に呼びます。
- `form.Subscribe`は`selector`で選んだ値が変わったときだけ再描画します。ボタンの状態はここで読みます。
- `canSubmit`は、未操作の間は`true`です。例外は`onMount`の検証がエラーを返した場合で、実測では未操作でも`false`になりました。

フィールド名は`defaultValues`から推論されます。上の登録フォームで`name="emial"`と打ち間違えると、tsc 7.0.2は次のエラーで止めます。数値のフィールドに`e.target.value`（文字列）をそのまま渡した場合もTS2345になります。

```
<form.Field name="emial">
// error TS2820: Type '"emial"' is not assignable to type '"email" | "password"'.
//   Did you mean '"email"'?
```

## バリデーションの書き方：zod・valibot・yupの渡し方と落とし穴

1系の検証は、フィールドの`validators`か`useForm`の`validators`に、実行するタイミングをキーにして書きます。同期は`onMount`・`onChange`・`onBlur`・`onSubmit`、非同期は`onChangeAsync`・`onBlurAsync`・`onSubmitAsync`で、`onMount`に非同期版はありません。関数を渡してエラー文字列を返す方法と、スキーマを渡す方法があります。

### zod・valibot・ArkTypeのスキーマ直接指定

1系はStandard Schemaという共通仕様に対応しており、[公式のValidationガイド](https://tanstack.com/form/latest/docs/framework/react/guides/validation)はZod・Valibot・ArkType・Effect Schemaを挙げています。上の登録フォームのように`validators: { onChange: signupSchema }`とフォーム単位で渡せば、各フィールドの`errors`にそのフィールドの分だけが配られます。古い記事にある`zodValidator()`などのアダプタ設定は不要です。仕組みは[Standard Schemaの全体像](/tech/details/11777/)、スキーマの書き方は[Zodの使い方入門](/tech/details/7391/)と[Valibotの解説](/tech/details/7584/)にまとめています。

### エラーは文字列ではなくissueオブジェクト

関数の検証で文字列を返した場合、`errors`は文字列の配列です。スキーマを渡した場合は`message`や`path`を持つオブジェクトの配列になり、zod 4.6.7のメール形式エラーは`code: "invalid_format"`を持つオブジェクトでした。公式サンプルの`field.state.meta.errors.join(',')`を流用すると画面に`[object Object]`と出るので、`err?.message`を取り出します。

### yupの非同期バリデーター指定

yup 1.7.1もStandard Schemaに対応していますが、検証結果を必ずPromiseで返します。これを`onBlur`に渡すと、フォーカスが外れた瞬間に`Error: async function passed to sync validator`が投げられます。型エラーにはならないので、実行するまで気づきません。`onBlurAsync`・`onChangeAsync`に渡せば正しくエラーが入ります。

```
import * as yup from 'yup'

<form.Field
  name="username"
  validators={{
    // onBlur に渡すと、フォーカスが外れた瞬間に
    // Error: async function passed to sync validator
    onBlurAsync: yup.string().required('必須です').min(3, '3文字以上で入力してください'),
  }}
>
```

### transformの変換結果とonSubmitでの再パース

スキーマの`transform`で文字列を数値に変えても、1系の`onSubmit`に届く`value`は入力時の値のままです。[公式のSubmission Handlingガイド](https://tanstack.com/form/latest/docs/framework/react/guides/submission-handling)も「The value passed to the onSubmit function will always be the input data.」と書いており、実測でも`age`は`'20'`（string）で届きました。変換後の値が必要なら`onSubmit`の中でもう一度`parse`します。v2ではこの再パースが不要になります（後述）。

```
const schema = z.object({ age: z.string().transform((v) => Number(v)) })

const form = useForm({
  defaultValues: { age: '20' },
  validators: { onChange: schema },
  onSubmit: ({ value }) => {
    // value.age は '20'（string）のまま届く
    const parsed = schema.parse(value) // parsed.age は 20（number）
    save(parsed)
  },
})
```

### 非同期検証とデバウンス

ユーザー名の重複確認のようにAPIを呼ぶ検証は`onChangeAsync`に書き、`onChangeAsyncDebounceMs`で間引きます。300msを指定して3回続けて入力した実測では、検証関数の呼び出しは最後の1回だけでした。同期と非同期の両方を書いた場合、非同期は同期側がエラーなしのときだけ走ります（`asyncAlways: true`で常に実行）。

```
<form.Field
  name="username"
  validators={{
    onChangeAsyncDebounceMs: 300,
    onChangeAsync: async ({ value }) =>
      (await isTaken(value)) ? 'このユーザー名は使われています' : undefined,
  }}
>
```

## 送信処理：handleSubmitとサーバー側エラーの戻し方

`form.handleSubmit()`は全フィールドの検証を走らせ、エラーがなければ`onSubmit`を呼びます。メールが不正なまま呼んだ実測では、`onSubmit`は一度も実行されませんでした。この節では、送信ボタンごとの処理の切り替え、サーバー側の検証結果の戻し方、未保存の変更の判定の3つを扱います。通信失敗やHTTPエラーの扱いは`onSubmit`の中で通常の`try`・`catch`として書きます。

- **送信ボタンで処理を分ける**：`useForm`に`onSubmitMeta`で既定値を置き、`form.handleSubmit({ submitAction: 'continue' })`のように引数を渡すと、`onSubmit`の`meta`で受け取れます。「保存して続ける」「保存して一覧へ」を1つのフォームで扱えます。
- **サーバーの検証結果を各欄に戻す**：フォーム単位の`onSubmitAsync`で送信前にAPIを呼び、`{ fields: { email: '登録済みです' } }`の形で返すと、該当フィールドのエラーとして表示されます。
- **未保存の変更**：`isDirty`は一度でも値を変えると、元に戻しても`true`のままです。初期値「a」を「b」にしてから「a」に戻した実測は`isDirty: true`・`isDefaultValue: true`でした。「未保存の変更があります」の表示には`isDefaultValue`を使います。

```
<form.Subscribe selector={(state) => state.isDefaultValue}>
  {(same) => (same ? null : <p>未保存の変更があります</p>)}
</form.Subscribe>
```

## 配列フィールドとcreateFormHook・withFormによる部品化

### mode=”array”がuseFieldArrayの代わり

React Hook Formの`useFieldArray`に当たる専用フックはなく、配列を持つフィールドに`mode="array"`を付けます。このとき値そのものではなく配列の変更回数を購読するため、要素の追加・削除のたびに一覧が描き直されます。操作は`pushValue`・`removeValue`・`insertValue`・`swapValues`で行い、要素の各項目は`` name={`members[${i}].name`} ``のような添字付きの名前で描画します。この名前もテンプレート文字列のまま型推論されます。

### createFormHookとwithFormによるフォームの部品化

[公式のForm Compositionガイド](https://tanstack.com/form/latest/docs/framework/react/guides/form-composition)は冒頭で「A common criticism of TanStack Form is that it is verbose out-of-the-box.」と認めており、その解決策が`createFormHook`です。自社のテキスト入力やボタンを一度登録すると、`form.AppField`の中から`field.TextField`として呼べます。大きなフォームを別ファイルに分けるときは、同じく`createFormHook`が返す`withForm`で子コンポーネントを作り、親の`form`をpropsで渡します。次のコードは配列部分を`withForm`で切り出した例で、tsc 7.0.2で型エラーなしを確認しました。

```
import { createFormHook, createFormHookContexts, formOptions } from '@tanstack/react-form'

export const { fieldContext, formContext, useFieldContext, useFormContext } =
  createFormHookContexts()

function TextField({ label }: { label: string }) {
  const field = useFieldContext<string>()
  return (
    <label>
      {label}
      <input
        value={field.state.value}
        onBlur={field.handleBlur}
        onChange={(e) => field.handleChange(e.target.value)}
      />
    </label>
  )
}

function SubmitButton({ label }: { label: string }) {
  const form = useFormContext()
  return (
    <form.Subscribe selector={(s) => s.isSubmitting}>
      {(isSubmitting) => <button type="submit" disabled={isSubmitting}>{label}</button>}
    </form.Subscribe>
  )
}

export const { useAppForm, withForm } = createFormHook({
  fieldContext,
  formContext,
  fieldComponents: { TextField },
  formComponents: { SubmitButton },
})

const profileOpts = formOptions({
  defaultValues: { name: '', members: [] as { name: string }[] },
})

// 配列部分を別コンポーネントに切り出す
const MembersSection = withForm({
  ...profileOpts,
  props: { title: 'メンバー' },
  render: function Render({ form, title }) {
    return (
      <form.Field name="members" mode="array">
        {(field) => (
          <fieldset>
            <legend>{title}</legend>
            {field.state.value.map((_, i) => (
              <form.AppField key={i} name={`members[${i}].name`}>
                {(sub) => <sub.TextField label={`メンバー${i + 1}`} />}
              </form.AppField>
            ))}
            <button type="button" onClick={() => field.pushValue({ name: '' })}>
              追加
            </button>
          </fieldset>
        )}
      </form.Field>
    )
  },
})

export function ProfileForm() {
  const form = useAppForm({
    ...profileOpts,
    onSubmit: ({ value }) => console.log(value),
  })
  return (
    <form
      onSubmit={(e) => {
        e.preventDefault()
        form.handleSubmit()
      }}
    >
      <form.AppField name="name">
        {(field) => <field.TextField label="氏名" />}
      </form.AppField>
      <MembersSection form={form} title="参加メンバー" />
      <form.AppForm>
        <form.SubmitButton label="保存" />
      </form.AppForm>
    </form>
  )
}
```

`withForm`に渡す`defaultValues`は型検査のためだけに使われるので、`formOptions`で作った設定を親子で共有すると二重定義を避けられます。`render`はアロー関数でなく`function Render`の形で書きます。公式FAQによると、アロー関数ではESLintがフックの呼び出し位置を誤検知します。

エラーのある欄へフォーカスを移す機能はTanStack Formにありません。公式のFocus Managementガイドも「we cannot add a built-in focus management feature」としており、入力要素への参照は部品側で用意します。React Hook Formで同じ処理をする`setFocus`の使い方は[MUIとReact Hook Formの連携](/tech/details/4113/)で扱っています。

## React Hook Formとの違いと選び方

| 比較軸              | TanStack Form                      | React Hook Form       |
| ---------------- | ---------------------------------- | --------------------- |
| 安定版（2026-11-04）  | 1.33.5                             | 7.91.0                |
| 次期版              | 2.0.0-alpha.3                      | 8.0.0-beta.5          |
| npm週間DL          | 6,257,176                          | 60,305,948            |
| 入力との結び方          | 制御型（value・handleChange）            | register中心の非制御型       |
| スキーマ検証           | Standard Schemaを直接渡す               | @hookform/resolvers経由 |
| 対応フレームワーク        | React・Vue・Angular・Solid・Svelte・Lit | React                 |
| useForm単体のgzip実測 | 17,639バイト                          | 12,388バイト             |
| フォーム全体の変更有無      | isDefaultValue                     | isDirty（初期値と比較）       |

週間DLは2026年10月28日〜11月3日のnpm集計で、React Hook Formが約10倍です。サイズは、`useForm`をimportして`console.log(useForm)`で参照を残した1ファイルを入口に、esbuild 0.28.2で`--bundle --minify --format=esm --external:react --external:react-dom`を指定してバンドルし、`gzip -9`で圧縮した参考値です（参照を残さないと未使用コードとして除去されます）。使うAPIの範囲で値は変わります。

### TanStack Formを選ぶ条件

- TanStack StartやTanStack Routerで組んでいて、サーバー関数と同じ型でフォームを検証したい（[TanStack Startの解説](/tech/details/10179/)参照）。
- ReactとVueなど複数のフレームワークで、検証ロジックと画面の考え方をそろえたい。
- 入力欄が数十ある業務フォームで、1欄の変更による再描画を`form.Subscribe`の単位で抑えたい。アンケートや申請フォームのように設問が多い画面を作る場合は、[アンケート管理システム開発](/service/system/enquetesystem/)のように画面と集計を一体で設計する選択肢もあります。

### React Hook Formのままでよい条件

既存のReact Hook Formのフォームが問題なく動いているなら、置き換える理由は薄いと判断します。制御型への書き換えは入力部品と`errors`の表示箇所の全てに及び、さらにTanStack Form自体がv2で書き方を変える途中です。今移して将来v2も採用する場合は、1系への書き換えとv2への書き換えを続けて行うことになります。React Hook Formの現在の書き方は[React Hook Formの使い方とv7の書き方](/tech/details/2898/)で解説しています。

## TanStack Form v2 alphaの変更点と移行の判断

v2は[2026年8月6日の公式ブログ](https://tanstack.com/blog/announcing-tanstack-form-v2-alpha)でalphaとして発表されました。ブログは「rebuilding the library from the ground up」と書いており、内部を作り直したうえで、v1で使いにくかった検証・リスナー・フォーム合成のAPIを設計し直しています。[公式の移行ガイド](https://github.com/TanStack/form/blob/alpha/docs/migrate-from-v1.md)から、日常のコードに影響する変更を抜き出すと次のとおりです。

| 項目      | v1（1.33.5）              | v2（2.0.0-alpha.3）      |
| ------- | ----------------------- | ---------------------- |
| 値・メタの参照 | field.state.value       | field.value・field.meta |
| エラー     | field.state.meta.errors | field.errors           |
| 検証の指定   | onChangeなどのキー           | run・triggersの配列        |
| デバウンス   | onChangeAsyncDebounceMs | triggerDebounceMs      |
| 配列      | mode=”array”            | form.ArrayField        |
| 部品の分割   | withForm                | formプロップを受ける通常の部品      |
| 変換後の値   | onSubmit内で再parse        | validatorOutputs       |
| 動作環境    | React 17〜19・CJSあり       | React 18以上・ESMのみ       |

2.0.0-alpha.3を入れて確かめた結果は次の3点です。

- **1系のコードはそのまま通らない**：`validators: { onChange: ... }`・`field.state.value`・`mode="array"`を含むコードをtsc 7.0.2にかけると、次の3種類の型エラーになりました。移行は型エラーを1つずつ潰す作業になります。
- **変換後の値が`onSubmit`に届く**：下のコードで送信すると、`value.age`は`'20'`、`validatorOutputs[0].age`は数値の`20`でした。検証エラーがあると`onSubmit`は呼ばれず、`handleSubmit()`の戻り値にエラーの配列が入ります。
- **移行ガイドの名前が古い**：ガイド本文は`schemaOutputs`と書いていますが、alpha.3の型定義に`schemaOutputs`はなく、リリースノートどおり`validatorOutputs`に改名済みです。alphaの間は、ガイドより型定義とリリースノートを優先して読みます。

```
error TS2353: Object literal may only specify known properties,
  and 'onChange' does not exist in type 'readonly FormValidator<{ n: string; }>[]'.
error TS2339: Property 'state' does not exist on type 'ReactFieldApi<"n", string, ...>'.
error TS2322: ... Property 'mode' does not exist on type ...
```

```
// @tanstack/react-form@2.0.0-alpha.3
const form = useForm({
  defaultValues: { email: '', age: '20' },
  validators: [{ run: schema, triggers: ['change'] }],
  onSubmit: async ({ value, validatorOutputs }) => {
    // value.age は '20'（入力値）、validatorOutputs[0].age は 20（変換後）
    await save(validatorOutputs[0])
  },
})

<form.Field name="email">
  {(field) => (
    <input
      value={field.value}
      onBlur={field.handleBlur}
      onChange={(e) => field.handleChange(e.target.value)}
      aria-invalid={field.meta.isInvalid}
    />
  )}
</form.Field>
```

`useForm`単体のgzip実測は21,669バイトで、1.33.5より約4KB増えました。公式ブログは「faster runtime performance」をうたっていますが、ブラウザで操作したときの速さはこの記事では測っていません。Vueアダプタは、2026年11月4日時点でrc（3.6.0-rc.14）にとどまるVue 3.6を必須とし、パッケージにはAIコーディングエージェント向けの`skills/`ディレクトリが8つ同梱されています。

移行の判断ははっきりしています。本番のフォームは1.33.5に固定し、v2はalphaが外れて移行ガイドが型定義と一致するまで待ちます。上の`validatorOutputs`への改名はalpha.2からalpha.3の1版で入ったものです（両版の型定義で確認）。逆に移行ガイドと公式APIリファレンスは、送信時に検証を飛ばす指定を`skipOnSubmit`と書いていますが、配布中のalpha.3の型定義にあるのは`runOnSubmit`だけで、`skipOnSubmit`は未リリースです。alphaのコードは版を上げるたびに直す前提になります。新規に書くコードは、`errors`を`message`で読む、`defaultValues`を必ずフォーム単位で書くなど、v2でも変わらない書き方に寄せておくと移行の手間が減ります。

## Vue・Svelte・React Native・Next.jsでの使い方

`defaultValues`・`validators`・`onSubmit`の設定はフレームワーク間で共通で、変わるのはフォームを作る関数と入力要素への結び方です。

- **Vue・Svelte・Solid・Angular・Lit**：フォームを作る関数は、Vueが`useForm`、SolidとSvelteが`createForm`、Angularが`injectForm`です。Litは`TanStackFormController`をコントローラーとして生成し、テンプレートから参照します。
- **React Native**：公式ガイドは「it should support React Native out-of-the-box」としており、追加設定はありません。`TextInput`の`onChangeText`に`field.handleChange`をそのまま渡します。
- **Next.js App Router・TanStack Start**：`@tanstack/react-form-nextjs`などの連携パッケージで、`createServerValidate`によりサーバー側に同じ検証を置き、返ってきた状態を`mergeForm`でクライアントのフォームへ戻します。

## よくある質問

### TanStack Formのnpmパッケージ名は何ですか？

Reactは`@tanstack/react-form`のようにフレームワーク名が入ります。通常のインストールで入るのは1.33.5で、v2を試す場合だけ`@tanstack/react-form@alpha`と指定します。

### React Hook FormとTanStack Formはどちらが速いですか？

操作時の応答速度を同じ条件で比べた公式の計測はなく、この記事でも測っていません。数字で比べられるのはバンドルサイズで、`useForm`単体のgzip実測はTanStack Formが17,639バイト、React Hook Formが12,388バイトでした。

### zodのエラーメッセージが\[object Object\]と表示されるのはなぜですか？

スキーマを渡したときの`errors`はオブジェクトの配列だからです。`field.state.meta.errors.map((err) => err?.message)`のように`message`を取り出して表示してください。v2でも`field.errors`の要素はオブジェクトで、同じく`message`を読みます。

### React Compilerと一緒に使えますか？

公式の[比較表](https://tanstack.com/form/latest/docs/comparison)ではTanStack FormのReact Compiler対応は✅、React Hook Formは🛑です。ただし同じページに「This comparison table is under construction and is still not completely accurate.」とあり、Devtoolsを「Planned」とする行も0.2.34が出ている現状と合いません。React Compilerを有効にした状態で入力と送信の動作を確かめてください。

### v2のalphaに移行すべきですか？

本番では移行しません。2.0.0-alpha.3（2026年10月23日）の時点でも改名を含む破壊的変更が続き、移行ガイドと型定義にもずれがあります。v2は安定版が出てから移行ガイドの順番どおりに進めます。

## 関連記事

- [React Hook Formとは？使い方とv7の書き方・検証タイミング【7.91対応】](/tech/details/2898/)
- [Standard Schemaとは？Zod・Valibot・ArkTypeを共通で受け取る仕組みと実装例](/tech/details/11777/)
- [Zodの使い方入門｜npm install zodとz.infer・safeParse【最新4.6.7・脆弱性修正】](/tech/details/7391/)
- [TanStack Startとは？1.0安定版の変更点と使い方・SEO設定・Bun/Dockerデプロイ【1.169】](/tech/details/10179/)
- [TanStack Queryとは？React Queryとの違い・v5の使い方と既定値の落とし穴](/tech/details/10307/)

---

出典: [TanStack Formとは？使い方とReact Hook Formとの違い・v2 alphaの変更点【v1.33】](<https://www.issoh.co.jp/tech/details/6350/>)（株式会社一創）
