如何在React中使用react-hook-form条件处理动态下拉选择框选项
基于react-hook-form实现字段数组下拉选项动态过滤方案
实现思路
核心逻辑是实时收集所有同组字段已选中的下拉值,在渲染每个字段的下拉框时过滤掉其他字段已占用的选项,保证每个选项只能被选中一次,新增字段时自动展示剩余可用选项。
具体实现步骤
- 先定义全局的原始下拉选项池,通过
useForm初始化表单默认值,调用useFieldArray管理字段数组的增删操作 - 使用
watch监听整个字段数组的变化,实时提取所有已选中的下拉值组成已选集合 - 渲染每个字段的下拉组件时,对原始选项做过滤:仅保留未被其他字段选中的选项,以及当前字段自身已选中的选项
- 新增字段时直接调用
append方法添加空值字段,下拉框会自动渲染当前剩余的可用选项,所有选项被选完时可禁用新增按钮避免无效操作
核心代码示例
import { useForm, useFieldArray, Controller } from "react-hook-form"; // 原始下拉选项池,可根据业务调整 const originalOptions = [ { value: "opt1", label: "选项1" }, { value: "opt2", label: "选项2" }, { value: "opt3", label: "选项3" }, { value: "opt4", label: "选项4" } ]; function DynamicFieldForm() { const { control, watch } = useForm({ defaultValues: { fieldList: [{ selectVal: "", inputVal: "" }] } }); const { fields, append } = useFieldArray({ control, name: "fieldList" }); // 实时获取所有字段已选的下拉值 const selectedValueSet = new Set( watch("fieldList").map(item => item.selectVal).filter(Boolean) ); return ( <div> {fields.map((field, index) => { // 过滤当前字段的可用选项 const curAvailableOptions = originalOptions.filter(opt => !selectedValueSet.has(opt.value) || opt.value === field.selectVal ); return ( <div key={field.id} style={{ margin: "8px 0" }}> <Controller control={control} name={`fieldList.${index}.selectVal`} render={({ field }) => ( <select {...field} style={{ marginRight: "8px" }}> <option value="">请选择</option> {curAvailableOptions.map(opt => ( <option key={opt.value} value={opt.value}> {opt.label} </option> ))} </select> )} /> <Controller control={control} name={`fieldList.${index}.inputVal`} render={({ field }) => ( <input {...field} placeholder="请输入补充内容" /> )} /> </div> ); })} <button onClick={() => append({ selectVal: "", inputVal: "" })} disabled={selectedValueSet.size === originalOptions.length} style={{ marginTop: "12px" }} > 新增字段 </button> </div> ); }
优化提示
若选项数量较多,可以使用
useMemo缓存selectedValueSet和每个字段的curAvailableOptions计算结果,减少重复计算开销,提升渲染性能。
如果业务允许同一个选项被多次选中,只需要调整过滤逻辑即可,不需要修改整体实现结构。
内容的提问来源于stack exchange,提问作者psilva.maf
相关产品推荐
相关产品推荐

