🌲系列一:跟着官方示例学习 @tanStack-form --- Simple
🌲系列二:跟着官方示例学习 @tanStack-form --- Array
这篇并没有采用官方的示例,代码部分也较为简单,因此直接在文章中展示,感兴趣的小伙伴可以粘贴至自己项目运行哦🤝
🌱 基础知识:什么是 linked fields?
在使用表单库时,我们经常会遇到这样的需求:某个字段的值变化后,另一个字段需要跟着联动更新或校验。所谓 linked fields,指的是 字段 A 的值变化后,影响字段 B 的行为,常见于:
- 输入"密码"后,"确认密码"字段需要实时校验一致性
- 选择国家后,联动显示对应城市选项
TanStack Form 提供了内建能力来实现这些需求,主要有两种方式:
validators.onChangeListenTo
: 用于跨字段验证<form.Subscribe />
: 适合更灵活的值同步或控制禁用等 UI 行为
🧪 场景一:确认密码字段验证(密码一致性)
最常见的联动场景:两个字段必须值相同。
首先我们可以看官方文档中提到的例子:
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
管理状态,表单数据仍是联动的