react-select Creatable:转换创建的选项

react-select Creatable: transforming created options

我尝试使用 react-select's Creatable select 组件来允许用户添加多个 CORS 源以注册到我的身份验证服务器。我希望能够允许用户粘贴完整的 URLs,并在将这些 URLs 添加到 Creatable [=] 后将其转换为 Origins(格式:<protocol>://<origin>[:port]) 37=].

例如,用户可以将 http://some-domain.com:1234/management/clients?param1=abc&param2=123#fragment_stuff 粘贴到 Creatable select 中,整个 URL 将自动成为 converted/added 作为其原始组件:http://some-domain.com:1234.

这是我编写的组件 (TypeScript) 的简化版本:

import CreatableSelect from 'react-select/creatable';
...


type MyOptionType = {
    label: string,
    value: string,
}

function SomeComponent(props:{}) {
    const [options, setOptions] = useState<MyOptionType[]>([]);

    const onOptionsChanged = (newOptions: OptionsType<MyOptionType>) => {
        // Get only options containing valid URLs, with valid origins
        const validUrlsWithOrigins = newOptions.filter(option => {
            try {
                return !!(new URL(option.value).origin);
            } catch (error) {
                return false;
            }
        });

        // Transform options (e.g.: "http://some-domain.com:1234/abc?def=ghi#jkl" will become "http://some-domain.com:1234")
        const newOptionsOrigins = validUrlsWithOrigins
            .map(option => new URL(option.value).origin)
            .map(origin => ({label: origin, value: origin}));
        setOptions(newOptionsOrigins);
    }

    return <CreatableSelect isMulti options={options} onChange={onOptionsChanged} />
}

在使用 React Developer Tools 进行调试时,我可以看到组件的状态正在相应地进行转换,只有 URLs 的 origin 部分是保持状态:

问题是 Creatable select 组件正在呈现完整的 URL 而不是仅呈现 URL 的来源:

为什么 Creatable select 与组件的状态不同步?有没有办法解决这个问题,或者是对 react-select?

的限制

你需要在这里区分两件事 - options CreatableSelect 的属性包含所有可能性的数组。但是这个组件的值是由 value 属性.

管理的

您可以查看 Multi-select text input 示例 on docs page 但基本上您需要:

单独保留值和选项:

const [options, setOptions] = React.useState<MyOptionType[]>([]);
const [value, setValue] = React.useState<MyOptionType[]>([]);

const createOption = (label: string) => ({
  label,
  value: label
});
<CreatableSelect
      isMulti
      options={options}
      value={options}
      onChange={onOptionsChanged}
    />

并修改您的 onOptionsChanged 函数

  1. 设置 value 已转换和验证的输入
  2. options 状态变量添加新选项(所有选项,无重复项)

这里有一些例子:

// Transform options (e.g.: "http://some-domain.com:1234/abc?def=ghi#jkl" will become "http://some-domain.com:1234")
    const newOptionsOrigins = validUrlsWithOrigins
      .map((option) => new URL(option.value).origin)
      .map((origin) => createOption(origin));

    setValue(newOptionsOrigins);

    //get all options without duplicates
    const allUniqueOptions: object = {};
    [...newOptionsOrigins, ...options].forEach((option) => {
      allUniqueOptions[option.value] = option.value;
    });
    setOptions(
      Object.keys(allUniqueOptions).map((option) => createOption(option))
    );
  };