我为我的react-project定制了一个react-select下拉组件。当我尝试使用React.HTMLAttributes扩展界面时
示例代码:
import * as React from "react";
import ReactSelect from 'react-select';
export interface SelectProps extends React.HTMLAttributes<HTMLSelectElement | HTMLInputElement> {
options: Array<any>;
isMulti: boolean;
isDisabled: boolean;
};
const Select: React.FC<SelectProps> = (props: SelectProps) => {
return (<div>
<label htmlFor={props.id}>{props.label}</label>
<div>
<ReactSelect
{...props}
/>
</div>
</div>)
}
export default Select;
使用上面的代码后,我无法获取props.id或props.name等
编辑:
React-Select v5 现在原生支持 TypeScript,因此进行了一些类型更改(详细信息)。
这是 v5 (react-select/async) 的更新示例,类似于 v4 的原始示例:
import ReactSelectAsync, { AsyncProps } from "react-select/async";
import { GroupBase } from "react-select";
interface CustomSelectAsyncProps {
additionalCustomProp: number;
}
function SelectAsync<
OptionType,
IsMulti extends boolean = false,
GroupType extends GroupBase<OptionType> = GroupBase<OptionType>
>({
additionalCustomProp,
...props
}: AsyncProps<OptionType, IsMulti, GroupType> & CustomSelectAsyncProps) {
return <ReactSelectAsync {...props} />;
}
export default SelectAsync;
原答案:
这记录在官方 react-select 文档中。
引用:
包装 Select 组件 通常,Select 组件被包装在整个应用程序中使用的另一个组件中,并且包装器应该与原始 Select 组件一样灵活(即,允许不同的选项类型、组、单选或多选)。为了提供这种灵活性,包装组件应该重新声明泛型并将它们转发到底层的 Select。以下是如何执行此操作的示例:
function CustomSelect<
Option,
IsMulti extends boolean = false,
Group extends GroupBase<Option> = GroupBase<Option>
>(props: Props<Option, IsMulti, Group>) {
return (
<Select {...props} theme={(theme) => ({ ...theme, borderRadius: 0 })} />
);
}
它还解释了如何使用额外的自定义道具来扩展道具:
您可以使用模块增强将自定义道具添加到选择道具类型中:
declare module 'react-select/dist/declarations/src/Select' {
export interface Props<
Option,
IsMulti extends boolean,
Group extends GroupBase<Option>
> {
myCustomProp: string;
}
}
但我个人更喜欢仅使用带有自定义界面的
&
字符来添加自定义界面来添加自定义道具(使用 ReactSelectAsync
的示例,请参阅 ... & CustomSelectAsyncProps
):
interface CustomSelectAsyncProps {
additionalCustomProp: number;
}
function SelectAsync<
OptionType extends OptionTypeBase,
IsMulti extends boolean = false,
GroupType extends GroupTypeBase<OptionType> = GroupTypeBase<OptionType>
>({
additionalCustomProp,
...props
}: Props<OptionType, IsMulti, GroupType> & CustomSelectAsyncProps) {
return (
<ReactSelectAsync {...props} />
);
}
你可以这样使用:
import React from 'react'
import { omit } from 'lodash';
import Select, { GroupBase, Props } from 'react-select';
type SelectProps<Option, IsMulti extends boolean = false, Group extends GroupBase<Option> = GroupBase<Option>> = Props<Option, IsMulti, Group> & {
label?: string;
id?: string;
}
const SearchableSelect = <
Option,
IsMulti extends boolean = false,
Group extends GroupBase<Option> = GroupBase<Option>
>(props: SelectProps<Option, IsMulti, Group>) => {
const id = props.id || Math.random().toString()
const reactSelectProps = omit(props, ['label', 'className'])
return (
<div>
{props.label && (
<label htmlFor={id} className="block text-sm font-medium text-gray-700">
{props.label}
</label>
)}
<Select
{...reactSelectProps}
theme={(theme) => ({
...theme,
colors: {
...theme.colors,
primary: "var(--primary-500)",
},
})}
/>
</div>
);
}
export default SearchableSelect
即使在阅读了这里的一些答案后,我仍然在努力尝试这种方法。
这是我的完整方法:
首先,ReactSelect 的 props 没有一个干净的界面,类似于扩展 Html 按钮的方式,例如:
Interface IbuttonProps extends HTMLButtonElement
react-select props 默认 props 的接口名称为
Props
,可以从这两个路径导入:
import { Props } from "react-select/dist/declarations/src/Select" instead import { Props } from "react-select"
只有后者
import { Props } from "react-select"
才是正确的!
Props
接口也使用泛型,所以它看起来类似于:
Props<Option,IsMulti,Group>
为了扩展此接口,我们将使用带有类型参数默认值的泛型类型定义,如下所示:
type MyCustomSelectProps<Option, IsMulti extends boolean = false, Group extends GroupBase<Option> = GroupBase<Option>> = Props<
Option,
IsMulti,
Group
>
因此,当我们创建自己的react-select Props扩展时,它将看起来像这样:
type MyCustomSelectProps<Option, IsMulti extends boolean = false, Group extends GroupBase<Option> = GroupBase<Option>> = Props<
Option,
IsMulti,
Group
> & {
MyCustomProperty:string;
MyOtherCustomProperty:number;
};
import * as Select from 'react-select';
import { GroupBase } from 'react-select';
import { Props } from 'react-select';
type SelectProps<Option, IsMulti extends boolean = false, Group extends GroupBase<Option> = GroupBase<Option>> = Props<
Option,
IsMulti,
Group
> & {
MyCustomProperty:string;
MyOtherCustomProperty:number;
};
export const Select = <Option, IsMulti extends boolean = false, Group extends GroupBase<Option> = GroupBase<Option>>(
props: SelectProps<Option, IsMulti, Group>,
) => {
return (<Select {...props}/>)
}
您可以直接从
Props
包导入 react-select
类型。您可能想要扩展它,以便要求 label
和 id
都被定义。
import React from "react";
import ReactSelect, { Props } from "react-select";
type SelectProps = Props & {
id: string;
label: string;
};
const Select: React.FC<SelectProps> = ({id, label, ...rest}) => {
return (
<div>
<label htmlFor={id}>{label}</label>
<div>
<ReactSelect {id, ...rest} />
</div>
</div>
);
};