Введение:
Необходимо написать компонент
Button
с использованием
React.forwardRef
, но с возможностью выбора отображаемого элемента, как это реализуется в некоторых библиотеках. Например, по умолчанию отображается элемент
button
, но если я передаю параметр
href
, то должна отображаться ссылка. Важный момент заключается в том, что мне нужно связать это поведение с
ref
- по умолчанию
ref
должен принимать ссылку типа
React.Ref<HTMLButtonElement>
, но если я передаю через
props
параметр
href
, то
ref
должен принимать ссылку типа
React.Ref<HTMLAnchorElement>
Попытки:
Пока не сильно разбираюсь в тонкостях языка, но вот что у меня получилось накидать.
Жалкие попытки...// общие параметры
type CommonProps = {
children: React.ReactNode
variant?: 'plain' | 'tonal' | 'filled' | 'outlined'
justify?: 'start' | 'center' | 'end'
}
type Props<T extends 'a' | 'button' | never> = (
T extends 'button' | 'a'
? T extends 'a'
? CommonProps & { href: string } & React.ComponentPropsWithoutRef<T>
: CommonProps & { href?: never } & React.ComponentPropsWithoutRef<T>
: CommonProps & { href?: never } & React.ComponentPropsWithoutRef<'button'>
)
const Button = React.forwardRef(<T extends 'a' | 'button' | never>(props: Props<T>, ref: React.Ref<React.ComponentRef<T>>) => {
if (typeof props.href === 'string') {
return (
<a className="button" ref={ref as React.Ref<React.ComponentRef<'a'>>}>
{props.children}
</a>
)
}
return (
<button className="button" ref={ref as React.Ref<React.ComponentRef<'button'>>}>
{props.children}
</button>
)
})
export default Button
Текущий результат:
На данный момент я чувствую что иду в нужном направлении, но все никак не могу понять что конкретно делаю не так, уже мозг вскипает, если честно. Повторюсь что конкретно я ожидаю:
Вызов
<Button />
должен ожидать атрибуты только для кнопки (
ButtonProps
);
Вызов
<Button href="/" />
должен ожидать атрибуты только для ссылки (
AnchorProps
);
Вызов
<Button ref={buttonRef} />
должен ожидать атрибуты только для кнопки (
ButtonProps
);
Вызов
<Button ref={anchorRef} />
должен ожидать атрибуты только для ссылки (
AnchorProps
).
Надеюсь понятно объяснил, заранее благодарю)