React Hook Form与Valibot条件必填输入字段问题
在React Hook Form + Valibot中处理条件字段校验的正确姿势
不用纠结register/unregister的频繁调用,核心是把条件校验逻辑放到Valibot的Schema里,配合React Hook Form的watch监听状态,就能实现「显示时必填、隐藏时不校验」的需求,下面给你具体实现步骤和代码:
1. 基础配置:初始化表单和Valibot Resolver
先确保安装了react-hook-form和@hookform/resolvers/valibot,然后初始化表单时指定Valibot作为校验器:
import { useForm } from 'react-hook-form'; import { valibotResolver } from '@hookform/resolvers/valibot'; import { object, string, optional, required, when } from 'valibot'; import { View, TextInput, Switch, Button, Text } from 'react-native'; export default function DynamicForm() { const { control, watch, handleSubmit, formState: { errors } } = useForm({ resolver: valibotResolver(formSchema), defaultValues: { name: '', showPhoneField: false, phone: '' } }); const showPhoneField = watch('showPhoneField');
2. 编写带条件逻辑的Valibot Schema
用Valibot的when方法定义条件校验规则:当控制字段显示的开关为true时,目标字段设为必填;否则设为可选(跳过校验):
const formSchema = object({ name: string([required('姓名不能为空')]), showPhoneField: boolean(), phone: when( (input) => input.showPhoneField, string([required('手机号不能为空')]), optional(string()) ) });
when方法的三个参数分别是:判断条件、满足条件时的校验规则、不满足时的规则。这样隐藏字段时,目标字段会被标记为可选,不会触发必填校验。
3. 渲染动态字段
根据监听的条件值控制字段显示隐藏,直接用control.setValue或register绑定字段即可,无需手动unregister:
const onSubmit = (data) => { console.log('提交的数据:', data); // 隐藏时目标字段不会触发校验错误,只会保留默认值或空字符串 }; return ( <View style={{ padding: 20 }}> <TextInput placeholder="姓名" value={watch('name')} onChangeText={(text) => control.setValue('name', text)} style={{ borderBottomWidth: 1, marginBottom: 10, paddingVertical: 8 }} /> {errors.name && <Text style={{ color: 'red', marginBottom: 10 }}>{errors.name.message}</Text>} <View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 10 }}> <Text>需要填写手机号?</Text> <Switch value={showPhoneField} onValueChange={(value) => control.setValue('showPhoneField', value)} style={{ marginLeft: 10 }} /> </View> {showPhoneField && ( <> <TextInput placeholder="手机号" value={watch('phone')} onChangeText={(text) => control.setValue('phone', text)} keyboardType="phone-pad" style={{ borderBottomWidth: 1, marginBottom: 10, paddingVertical: 8 }} /> {errors.phone && <Text style={{ color: 'red', marginBottom: 10 }}>{errors.phone.message}</Text>} </> )} <Button title="提交" onPress={handleSubmit(onSubmit)} /> </View> ); }
为什么不用register/unregister?
频繁调用register和unregister会导致表单状态频繁更新,容易出现校验状态不同步的问题。而通过Valibot的Schema条件判断,校验逻辑和字段显示逻辑完全绑定,更稳定可靠,也符合React Hook Form和Valibot的设计思路。
额外技巧:处理复杂条件
如果条件依赖多个字段,直接在when的判断函数里组合即可:
phone: when( (input) => input.showPhoneField && input.userType === 'personal', string([required('手机号不能为空')]), optional(string()) )
内容的提问来源于stack exchange,提问作者Sanjay
相关产品推荐
相关产品推荐

