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

如何在react-querybuilder中过滤FieldSelector已使用字段

解决React Query Builder自定义FieldSelector移除已用字段的问题

问题核心

需要实现:新增规则时FieldSelector仅显示未被使用的字段,但原有规则的FieldSelector仍能保留自身已选字段(支持修改)。之前的错误是直接过滤所有已用字段,导致原有规则的选项被错误移除。

解决方案思路

区分当前FieldSelector所属的规则状态,针对性过滤选项:

  • 已存在的规则:保留当前选中的字段,同时显示其他未被使用的字段
  • 新增的规则:仅显示未被其他规则使用的字段

关键逻辑是收集已用字段时,排除当前规则自身的字段值,避免把当前规则的选项过滤掉。

修改后的FieldSelector组件代码

const FieldSelector = (props: FieldSelectorProps) => {
  const { control, setValue, getValues } = useFormContext();
  const namePrefix = `${name}[${props.path[0]}]`;

  const rules = getValues(name);
  // 获取当前规则的字段值
  const currentField = props.value;

  // 收集已使用的字段,排除当前规则自身的字段
  const usedFields = new Set(
    rules?.filter(rule => rule.field !== currentField)
          ?.map(rule => rule.field)
  );

  // 分状态过滤选项
  const filteredOptions = (props.options as FullOption[]).filter(option => {
    if (currentField) {
      // 已存在的规则:保留当前选中字段 + 未被其他规则使用的字段
      return option.value === currentField || !usedFields.has(option.value);
    }
    // 新增规则:仅显示未被使用的字段
    return !usedFields.has(option.value);
  });

  return (
    <div className="flex">
      <FormField
        control={control}
        name={`${namePrefix}.field`}
        rules={{ required: true }}
        render={({ field }) => (
          <Select
            value={field.value}
            onValueChange={(d) => {
              props.handleOnChange(d);
              field.onChange(d);
              if (props.value !== d) {
                setValue(`${namePrefix}.value`, [], { shouldDirty: true });
              }
            }}
            disabled={props.disabled}
          >
            <SelectTrigger className="h-10 min-w-[120px] w-fit">
              <SelectValue placeholder={props.value} data-testid="qb-field-selector" />
            </SelectTrigger>
            <SelectContent side="bottom">
              {filteredOptions.map((p: BaseOption, index: number) => (
                <SelectItem key={index} value={`${p.value}`}>
                  {p.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        )}
      />
    </div>
  );
};

关键修改点说明

  1. 排除当前规则字段:收集已用字段时,通过filter(rule => rule.field !== currentField)排除当前规则的字段,避免把自身选项过滤掉。
  2. 分状态过滤选项:
    • 当规则已有选中字段,保留当前字段和未被其他规则使用的字段,确保原有规则的FieldSelector能正常显示自身选项。
    • 当规则是新增状态,仅显示未被使用的字段,符合新增规则的需求。
  3. 渲染过滤后的选项:将原来的props.options替换为filteredOptions,确保下拉框显示正确的选项。

内容的提问来源于stack exchange,提问作者Muhammad Zahid Iqbal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 16:27:33