gpt4 book ai didi

reactjs - typescript :React.forwardRef 带有来自@material-ui 的通用 Prop

转载 作者:行者123 更新时间:2023-12-03 13:41:29 35 4
gpt4 key购买 nike

我正在尝试在 @material-ui Button 组件之上添加自定义逻辑。为此,我正在创建一个包装原始 Button 的组件,并且它可以正常运行。
我的问题是正确输入这个,特别是从原始组件中获取 Prop 。我通过关注 https://material-ui.com/guides/typescript/#usage-of-component-prop 让它工作了直到我添加 React.forwardRef() .
不带工作版本 forwardRef :

import { Button, ButtonProps } from '@material-ui/core'
import React from 'react'

type ExtraProps = {
target?: string
rel?: string
href?: string
color?: 'default' | 'primary' | 'secondary'
}

// see https://material-ui.com/guides/typescript/#usage-of-component-prop
type Props<C extends React.ElementType> = ButtonProps<C, { component?: C }> & ExtraProps

const CustomButton = <C extends React.ElementType>({
children,
target,
rel,
href,
...rest
}: Props<C>) => {
const relValue = target === '_blank' ? 'noopener noreferrer' : rel

const linkValues = href ? { href, target, rel: relValue } : undefined

return (
<Button {...linkValues} {...rest}>
{children}
</Button>
)
}
非工作版本 React.forwardRef :
import { Button, ButtonProps } from '@material-ui/core'
import React from 'react'

type ExtraProps = {
target?: string
rel?: string
href?: string
color?: 'default' | 'primary' | 'secondary'
}

// see https://material-ui.com/guides/typescript/#usage-of-component-prop
export type Props<C extends React.ElementType> = ButtonProps<C, { component?: C }> & ExtraProps

const CustomButton = React.forwardRef<HTMLButtonElement, Props<React.ElementType>>(
({ children, target, rel, href, ...rest }, ref) => {
const relValue = target === '_blank' ? 'noopener noreferrer' : rel

const linkValues = href ? { href, target, rel: relValue } : undefined

return (
<Button {...linkValues} {...rest} ref={ref}>
{children}
</Button>
)
}
)
当我说“不工作”时,是因为 CustomButton 的类型是:
React.ForwardRefExoticComponent<Pick<Props<React.ElementType<any>>, string | number | symbol> & React.RefAttributes<HTMLButtonElement>>
代替
<C extends React.ElementType<any>>({ children, target, rel, href, ...rest }: Props<C>) => JSX.Element
这意味着我可以将任何 Prop 传递给我的 CustomButton并且 TS 根本不会执行契约(Contract)。
我应该如何使用 React.forwardRef() 修复版本为了正确打字?
代码沙盒演示: https://codesandbox.io/s/boring-hertz-0hutt?file=/src/App.tsx

最佳答案

forwardRef 不是通用的。是万恶之源。我也在努力实现类型安全。现在我有这个解决方案:

type As = 'button' | 'a' | 'span';

type Element<T extends As = 'button'> = T extends 'span'
? HTMLSpanElement
: T extends 'a'
? HTMLAnchorElement
: HTMLButtonElement;

interface CommonButtonProps<T extends As> {
view?: View;
size?: Size;
disabled?: boolean;
iconLeft?: ReactElement;
iconRight?: ReactElement;
className?: string;
progress?: boolean;
baseElement?: T;
}

export type ButtonProps<T extends As = 'button'> = CommonButtonProps<T> &
(T extends 'a'
? JSX.IntrinsicElements['a']
: T extends 'span'
? JSX.IntrinsicElements['span']
: T extends undefined
? JSX.IntrinsicElements['button']
: JSX.IntrinsicElements['button']);

const Button = (
{ children, baseElement, ...props }: PropsWithChildren<ButtonProps<As>>,
ref: React.Ref<Element<As>>,
) => {
return (
<StyledButton {...props} as={baseElement} ref={ref}>
{children}
</StyledButton>
);
};

function genericForwardRef<T extends ForwardRefRenderFunction<any, any>>(Component: T) {
const ForwardedComponent = forwardRef(Component);

return <U extends As = 'button'>(
props: PropsWithChildren<PropsWithoutRef<ButtonProps<U>> & RefAttributes<Element<U>>>,
) => <ForwardedComponent {...props} />;
}

export default genericForwardRef(Button);

(注意:我正在使用样式组件)

关于reactjs - typescript :React.forwardRef 带有来自@material-ui 的通用 Prop ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62642843/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com