跟着官方示例学习 @tanStack-form --- Linked Fields

🌲系列一:跟着官方示例学习 @tanStack-form --- Simple

🌲系列二:跟着官方示例学习 @tanStack-form --- Array


这篇并没有采用官方的示例,代码部分也较为简单,因此直接在文章中展示,感兴趣的小伙伴可以粘贴至自己项目运行哦🤝

🌱 基础知识:什么是 linked fields?

在使用表单库时,我们经常会遇到这样的需求:某个字段的值变化后,另一个字段需要跟着联动更新或校验。所谓 linked fields,指的是 字段 A 的值变化后,影响字段 B 的行为,常见于:

  • 输入"密码"后,"确认密码"字段需要实时校验一致性
  • 选择国家后,联动显示对应城市选项

TanStack Form 提供了内建能力来实现这些需求,主要有两种方式:

  • validators.onChangeListenTo: 用于跨字段验证
  • <form.Subscribe />: 适合更灵活的值同步或控制禁用等 UI 行为

🧪 场景一:确认密码字段验证(密码一致性)

最常见的联动场景:两个字段必须值相同。

首先我们可以看官方文档中提到的例子:

tanstack.com/form/latest...

tsx 复制代码
function App() {
  const form = useForm({
    defaultValues: {
      password: '',
      confirm_password: '',
    },
    // ...
  })

  return (
    <div>
      <form.Field name="password">
        {(field) => (
          <label>
            <div>Password</div>
            <input
              value={field.state.value}
              onChange={(e) => field.handleChange(e.target.value)}
            />
          </label>
        )}
      </form.Field>
      <form.Field
        name="confirm_password"
        validators={{
          onChangeListenTo: ['password'],
          onChange: ({ value, fieldApi }) => {
            if (value !== fieldApi.form.getFieldValue('password')) {
              return 'Passwords do not match'
            }
            return undefined
          },
        }}
      >
        {(field) => (
          <div>
            <label>
              <div>Confirm Password</div>
              <input
                value={field.state.value}
                onChange={(e) => field.handleChange(e.target.value)}
              />
            </label>
            {field.state.meta.errors.map((err) => (
              <div key={err}>{err}</div>
            ))}
          </div>
        )}
      </form.Field>
    </div>
  )
}

🔍 要点说明: onChangeListenTo: 'password' 表示"监听 password 字段"

使用 fieldApi.form.getFieldValue('password') 获取 password 的当前值进行对比

📘 延伸阅读:getFieldValue API 🔗

🧪 场景二:选择国家 → 自动填写城市

除了验证类联动,setFieldValue 可以在字段变化时,主动设置另一个字段的值。

比如:当用户选择国家时,自动填写该国家的首都。

tsx 复制代码
<form>
  <div>
    <form.Field
      name="country"
      validators={{
        onChange: ({ value }) => {
          // 看这里 👈👈👈
          const options = citiesMap[value as "China" | "USA"] || "";
          form.setFieldValue("city", options);
        },
      }}
    >
      {(field) => (
        <label>
          <div>Select Country</div>
          <select onChange={(e) => field.handleChange(e.target.value)}>
            <option value="China">China</option>
            <option value="USA">USA</option>
          </select>
        </label>
      )}
    </form.Field>
  </div>
  <div>
    <form.Field name="city">
      {(field) => (
        <div>
          <label>
            <div>City</div>
            <input value={field.state.value} disabled />
          </label>
        </div>
      )}
    </form.Field>
  </div>
</form>;

📘 延伸阅读:setFieldValue API 🔗

🧪 场景三:选择国家 → 联动城市下拉框

这一场景稍微复杂一点,涉及到联动选项更新。推荐使用 <form.Subscribe /> 实现响应式更新。

tsx 复制代码
<form>
  <div>
    <form.Field name="country">
      {(field) => (
        <label>
          <div>Select Country</div>
          <select onChange={(e) => field.handleChange(e.target.value)}>
            <option value="China">China</option>
            <option value="USA">USA</option>
          </select>
        </label>
      )}
    </form.Field>
  </div>
  <div>
    <form.Subscribe selector={(state) => state.values.country}>
      {(country) => (
        <form.Field name="city">
          {(field) => {
            const options = citiesMap[country as "China" | "USA"] || [];
            return (
              <div>
                <label>
                  <div>City</div>
                  <select
                    value={field.state.value}
                    onChange={(e) => field.handleChange(e.target.value)}
                  >
                    {options.map((city: string) => (
                      <option key={city} value={city}>
                        {city}
                      </option>
                    ))}
                  </select>
                </label>
              </div>
            );
          }}
        </form.Field>
      )}
    </form.Subscribe>
  </div>
</form>;

🔍 要点说明:

  • form.Subscribe 可以监听任意字段的变化,并触发 UI 重新渲染

  • citiesMap[country] 实时更新城市下拉列表的选项

  • 城市字段仍通过 form.Field 管理状态,表单数据仍是联动的

相关推荐
子兮曰1 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师1 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学1 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端