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

切换Link下拉框时DropdownSection默认选项未正确设置问题

问题描述

我有一个Link下拉框,切换它会更新对应的DropdownSection组件(该组件包含不同的选项数组)。需求是:

  • 切换到不同Link时,若对应选项数组长度大于1,DropdownSection的默认选项设为第二个选项(跳过第一个“No Selection”选项),比如选择Link 2时应选中“Three”选项。

当前存在的问题:当手动选中DropdownSection的某个选项后,再切换Link下拉框,DropdownSection的选中项会变成空白。

初始状态:应用加载时,Link 1为默认选中项,DropdownSection默认选中“One”选项。
切换Link 2后的预期状态:DropdownSection默认选中“Three”选项。


示例代码(设置默认选项)
<DropdownSection
  label={linkOptions[0].text}
  options={link1Options}
  defaultOptionText={link1Options.length > 1 ? link1Options[1].text : "No Selection"}
  defaultOptionValue={link1Options.length > 1 ? link1Options[1].value : "0"}
/>

现有组件代码

App组件

const App = ({}) => {
  const linkOptions = [
    {
      text: "Link 1",
      value: "1",
    },
    {
      text: "Link 2",
      value: "2",
    },
    {
      text: "Link 3",
      value: "3",
    },
  ];

  const [link, setLink] = useState(linkOptions[0].value);

  const link1Options = [
    {
      text: "No Selection",
      value: "0",
    },
    {
      text: "One",
      value: "1"
    },
    {
      text: "Two",
      value: "2"
    },
  ];
  const link2Options = [
    {
      text: "No Selection",
      value: "0",
    },
    {
      text: "Three",
      value: "3"
    },
    {
      text: "Four",
      value: "4"
    },
  ];
  const link3Options = [
    {
      text: "No Selection",
      value: "0",
    },
    {
      text: "Five",
      value: "5"
    },
    {
      text: "Six",
      value: "6"
    },
  ];

  let linkDropdownSection = <></>;
  if (link === linkOptions[0].value) {
    linkDropdownSection = (
      <DropdownSection
        label={linkOptions[0].text}
        options={link1Options}
        defaultOptionText={link1Options.length > 1 ? link1Options[1].text : "No Selection"}
        defaultOptionValue={link1Options.length > 1 ? link1Options[1].value : "0"}
      />
    );
  } else if (link === linkOptions[1].value) {
    linkDropdownSection = (
      <DropdownSection
        label={linkOptions[1].text}
        options={link2Options}
        defaultOptionText={link2Options.length > 1 ? link2Options[1].text : "No Selection"}
        defaultOptionValue={link2Options.length > 1 ? link2Options[1].value : "0"}
      />
    );
  } else if (link === linkOptions[2].value) {
    linkDropdownSection = (
      <DropdownSection
        label={linkOptions[2].text}
        options={link3Options}
        defaultOptionText={link3Options.length > 1 ? link3Options[1].text : "No Selection"}
        defaultOptionValue={link3Options.length > 1 ? link3Options[1].value : "0"}
      />
    );
  }

  // @ts-ignore: next-line - Ignore event parameter
  const onLinkSelect: DropdownProps["onOptionSelect"] = (event: any, data: any) => {
    setLink(data.optionValue);
  };

  return (
    <>
      <main>
        {
          <section>
            <Dropdown
              defaultValue={linkOptions[0].text}
              defaultSelectedOptions={[linkOptions[0].value]}
              onOptionSelect={onLinkSelect}
            >
              {linkOptions.map((option) => (
                <Option key={`${optionId}-${option.value}`} value={option.value}>
                  {option.text}
                </Option>
              ))}
            </Dropdown>
            {linkDropdownSection}
          </section>
        }
      </main>
    </>
  );
};
const DropdownSection = ({
  label,
  options,
  defaultOptionText,
  defaultOptionValue,
}) => {
  const optionId = useId("option");

  return (
    <section>
      <div>
        <Label>{label}</Label>
        <Dropdown
          defaultValue={defaultOptionText}
          defaultSelectedOptions={[defaultOptionValue]}
          onOptionSelect={onContactSelect}
        >
          {options.map((option) => (
            <FluentUIOption key={`${optionId}-${option.value}`} value={option.value}>
              {option.text}
            </FluentUIOption>
          ))}
        </Dropdown>
      </div>
      <Divider />
    </section>
  );
};

问题原因

当前DropdownSection使用defaultValue和defaultSelectedOptions这两个非受控组件属性,它们仅在组件第一次挂载时生效。当用户手动选择选项后,组件内部会维护自身状态;切换Link时,虽然DropdownSection重新渲染,但React可能复用已有组件实例,导致内部状态未被重置,从而出现选中项空白的情况。


解决方案

将DropdownSection改为受控组件,由父组件(App)控制其选中状态,切换Link时强制重置选中值:

步骤1:在App组件中添加选中值状态

const App = ({}) => {
  // ... 原有代码
  const [selectedOptionValue, setSelectedOptionValue] = useState('');

  // 初始化默认选中值
  useEffect(() => {
    const initialOptions = link1Options;
    setSelectedOptionValue(initialOptions.length > 1 ? initialOptions[1].value : "0");
  }, []);

  // 切换Link时重置选中值
  useEffect(() => {
    let currentOptions;
    if (link === linkOptions[0].value) {
      currentOptions = link1Options;
    } else if (link === linkOptions[1].value) {
      currentOptions = link2Options;
    } else {
      currentOptions = link3Options;
    }
    setSelectedOptionValue(currentOptions.length > 1 ? currentOptions[1].value : "0");
  }, [link]);

  // ... 原有代码
};

步骤2:修改DropdownSection的props传递受控属性

替换App中渲染DropdownSection的逻辑,传递selectedValue和onOptionChange:

// Link 1对应的DropdownSection示例
linkDropdownSection = (
  <DropdownSection
    label={linkOptions[0].text}
    options={link1Options}
    selectedValue={selectedOptionValue}
    onOptionChange={setSelectedOptionValue}
  />
);
// 其他Link对应的DropdownSection同理,移除default相关属性

步骤3:重构DropdownSection为受控模式

const DropdownSection = ({
  label,
  options,
  selectedValue,
  onOptionChange,
}) => {
  const optionId = useId("option");

  const handleSelect = (event, data) => {
    onOptionChange(data.optionValue);
  };

  // 匹配选中值对应的文本
  const selectedText = options.find(opt => opt.value === selectedValue)?.text || "No Selection";

  return (
    <section>
      <div>
        <Label>{label}</Label>
        <Dropdown
          value={selectedText}
          selectedOptions={[selectedValue]}
          onOptionSelect={handleSelect}
        >
          {options.map((option) => (
            <FluentUIOption key={`${optionId}-${option.value}`} value={option.value}>
              {option.text}
            </FluentUIOption>
          ))}
        </Dropdown>
      </div>
      <Divider />
    </section>
  );
};

步骤4:优化App组件的DropdownSection渲染逻辑(可选)

用对象映射替代多个if-else,简化代码:

const linkOptionMap = {
  "1": { options: link1Options, label: linkOptions[0].text },
  "2": { options: link2Options, label: linkOptions[1].text },
  "3": { options: link3Options, label: linkOptions[2].text },
};

const currentLinkConfig = linkOptionMap[link];
const linkDropdownSection = (
  <DropdownSection
    label={currentLinkConfig.label}
    options={currentLinkConfig.options}
    selectedValue={selectedOptionValue}
    onOptionChange={setSelectedOptionValue}
  />
);

内容的提问来源于stack exchange,提问作者tomtomdam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 20:12:32