You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 12:12:19