React/React+Redux中如何移除所有下拉框内已被选中的可选值
实现方案
完全不需要额外引入Redux增加复杂度,直接用react-hook-form自带的能力就能实现,核心逻辑是监听所有下拉框的选中值集合,动态过滤每个下拉框的可选列表即可。
核心实现步骤
- 用
watchAPI监听useFieldArray对应字段数组的所有值,拿到全局已选值的集合 - 对初始可选列表做过滤:排除所有已被选中的值,如果需要保留当前下拉框自身的选中值(避免选中后展开下拉看不到自己选的项,建议加这个逻辑),额外保留当前下标对应的选中值即可
- 表单值变化时
watch会自动触发重渲染,可选列表会同步更新
完整代码示例
import { useForm, useFieldArray, useMemo } from 'react-hook-form' // 初始全量可选值 const ALL_OPTIONS = ['apple', 'banana', 'pineapple', 'pear', 'mango'] function SelectArray() { const { control, watch, register } = useForm({ defaultValues: { // 初始化3个下拉框,默认值为空 fruits: Array(3).fill('') } }) const { fields } = useFieldArray({ control, name: 'fruits' }) // 监听所有下拉框的选中值 const selectedValues = watch('fruits') // 用useMemo缓存已选值集合,避免重复计算 const selectedSet = useMemo(() => { return new Set(selectedValues.filter(Boolean)) // 过滤掉未选择的空值 }, [selectedValues]) return ( <div> {fields.map((item, index) => { // 生成当前下拉框的可选列表 const currentOptions = useMemo(() => { return ALL_OPTIONS.filter(opt => { // 逻辑1:保留当前下拉框自己的选中值,其余已选值全部移除(体验更好) return !selectedSet.has(opt) || opt === selectedValues[index] // 逻辑2:所有已选值全部移除(完全匹配你举的示例效果) // return !selectedSet.has(opt) }) }, [selectedSet, selectedValues[index]]) return ( <select key={item.id} {...register(`fruits.${index}`)} style={{ display: 'block', margin: '8px 0' }} > <option value="">请选择</option> {currentOptions.map(opt => ( <option key={opt} value={opt}>{opt}</option> ))} </select> ) })} </div> ) }
结合Redux的场景处理
如果你的选中值需要全局共享,才需要用到Redux:
- 监听表单的
fruits字段变化,值更新时同步dispatch到Redux存储 - 后续可选列表的过滤逻辑不变,只是把
selectedValues的来源从watch换成Redux里存储的对应字段即可
内容的提问来源于stack exchange,提问作者Johnexe
相关产品推荐
相关产品推荐

