[v2] [RFC] What should happen when `Field` and `FormGroup` unmount?

オープン
#2,296 コメント 3 件 リアクション 1 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
25/100
issue の種類
機能追加
明瞭さ
説明が足りない
活発さ
静か
技術スタック
react, typescript
領域
frontend

調査の方向性

実装ファイルやテストは指定されていません。まず、RFC で説明されている useForm、Field、FormGroup、form.handleSubmit のエントリーポイントをたどり、その後、それらのライフサイクル動作を比較してください。実装作業の範囲を決められる状態にするには、アンマウントされたリスナー、バリデーター、フォームレベルの状態についてのデフォルトを合意する必要があります。

索引モデルが issue の本文から書いたものです。

説明

area: runtime scope: core v2

RFC: What should happen when Field and FormGroup unmount?

In TanStack Form, a Field or FormGroup follows the lifecycle of the UI component that renders it: it mounts and unmounts with that component. After it unmounts, the form may still retain state and behavior associated with it. This leaves us with an important question: should unmounting only stop the field or group from rendering, or should it also change how it participates in the form?

This RFC looks at what should happen to that retained state and behavior once the corresponding UI is no longer mounted.

The problem

Once a field has mounted, the form keeps state associated with it. This includes metadata such as whether the field has been touched, along with any validation errors.

Some field state also contributes to the state of the form as a whole. For example, changing a field sets that field's isTouched state to true. It also sets form.state.isTouched to true, because the form-level value tells us whether any field has been touched.

When an application explicitly deletes or resets a field, it is clear that the field's state is meant to change. The form can update its form-level state at the same time, and those explicit actions give us a clear point at which to decide what should happen to the field's validators and listeners.

Unmounting does not carry the same intent. A field might disappear because the user moved to another step, switched tabs, or scrolled it out of a virtualized view. The field is no longer rendered, but the user did not necessarily delete or reset it. We therefore need to decide whether unmounting should affect only the UI or also the field's role in the form.

The ambiguity

A two-step form makes the issue easier to see. In this example, the first step contains a name field and the second step contains the submit button. The code uses React syntax, but the same lifecycle question applies to other UI frameworks:

import { useState } from 'react'
import { useForm } from '@tanstack/react-form'

function SignupForm() {
  const [step, setStep] = useState(1)
  const form = useForm({
    defaultValues: { name: '' },
    onSubmit: ({ value }) => console.log(value),
  })

  return (
    <form
      onSubmit={(event) => {
        event.preventDefault()
        form.handleSubmit()
      }}
    >
      {step === 1 ? (
        <>
          <form.Field
            name="name"
            validators={[
              {
                // Validators run on submission by default.
                triggers: [],
                run: ({ value }) =>
                  value ? undefined : 'Please enter your name',
              },
            ]}
          >
            {(field) => (
              <input
                value={field.value}
                onChange={(event) => field.handleChange(event.target.value)}
              />
            )}
          </form.Field>
          <button type="button" onClick={() => setStep(2)}>
            Next
          </button>
        </>
      ) : (
        <button type="submit">Submit</button>
      )}
    </form>
  )
}

Clicking Next unmounts the name field, but its value remains in the form. The field is now absent from the UI while still being part of the form's stored data. What should happen when the user submits from the second step? Should the unmounted field's validator still run? If the user edited the field before moving on, should the form still be considered touched? If the field has a listener, should that listener remain active even though the field is no longer rendered?

More generally, we need to decide which parts of an unmounted field should continue to participate in the form:

  1. If the field has a listener, should that listener remain active after the field unmounts, or should it stop being called?
  2. If the field has a validator, should that validator still run as part of form.handleSubmit(), or should it be disabled while the field is unmounted?
  3. Should form-level state such as isTouched include every field the form knows about, or only the fields that are currently mounted?

The same questions apply to FormGroup, which also follows the lifecycle of a rendered component.

Why this matters

  • Virtualized or dynamically rendered fields are frequently mounted and unmounted as the visible UI changes. Their behavior should not be surprising simply because they moved out of view.
  • In a multi-step form, switching steps may unmount an entire group. We need to know whether that group still participates in the final submission.
  • Persistent form state such as isPristine could change only because a different set of fields is currently rendered, even if the user did not change any values.

The goal of this RFC is to agree on a predictable default for these cases. We would especially like to hear about use cases where mounted and unmounted fields need to behave differently.

主要言語
TypeScript
スター
6.8k
フォーク
705
平均マージ
1日 12時間
マージ済み PR(30日)
14

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

TanStack/form のほかの issue

TanStack/form の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。