React Hook Form 校验字段数组不同索引多字段值唯一性
React Hook Form 数组字段重复值校验方案
优先实现:字段级实时校验(提交前自动触发)
你原来的validate逻辑写法有误,不需要传当前值v给getValues,直接在校验函数里拉取整个documents数组做重复判断即可,修改后的代码如下:
<Select {...register(`documents.${index}.language`, { validate: (currentLang) => { // 获取整个文档数组的所有值 const allDocs = getValues('documents') || []; // 提取所有已填写的语言值,过滤空项 const allSelectedLangs = allDocs.map(item => item?.language).filter(Boolean); // 统计当前语言出现次数,超过1即为重复 const isDuplicate = allSelectedLangs.filter(lang => lang === currentLang).length > 1; return !isDuplicate || '语言选项不能重复'; } })} sx={{ textAlign: 'center' }} > {availableLanguages ?.sort((a) => (a.name === 'pl' ? -1 : 1)) // 排序将波兰语设为默认首选项 .map((language) => ( <option key={language.name} value={language.name}> {language.name.toUpperCase()} </option> ))} </Select>
这个方案的特点:
- 单个字段值修改、数组增删条目时都会自动触发校验,用户在填写过程中就能看到重复提示,不用等到点击提交按钮
- 校验逻辑完全接入React Hook Form的原生校验流,错误信息可以直接通过
formState.errors.documents获取渲染,不需要额外维护错误状态
备选实现:提交阶段全局校验
如果你需要在提交时统一做校验,可以在提交回调里加去重判断,逻辑更简单:
const onSubmit = (formData) => { const selectedLangs = formData.documents.map(item => item.language).filter(Boolean); // 利用Set去重后长度和原数组对比,判断是否有重复 const hasDuplicateLang = new Set(selectedLangs).size !== selectedLangs.length; if (hasDuplicateLang) { // 可以通过setError手动挂载表单错误 setError('documents.root', { type: 'duplicate', message: '所有文档的语言选项不能重复' }); return; } // 校验通过后执行后续提交逻辑 }
提示:如果你的
documents是动态增减的数组,优先选第一种字段级校验方案,不需要手动触发校验重跑,体验更流畅。
内容的提问来源于stack exchange,提问作者espezaliate
相关产品推荐
相关产品推荐

