使用Typescript进行反应—使用React.forwardRef时的泛型

我正在尝试创建一个通用组件,用户可以在其中将自定义传递OptionType给组件以一路进行类型检查。此组件还需要一个React.forwardRef

我可以在没有forwardRef的情况下使其正常工作。有任何想法吗?代码如下:

export interface Option<OptionValueType = unknown> {

value: OptionValueType;

label: string;

}

interface WithoutForwardRefProps<OptionType> {

onChange: (option: OptionType) => void;

options: OptionType[];

}

export const WithoutForwardRef = <OptionType extends Option>(

props: WithoutForwardRefProps<OptionType>,

) => {

const { options, onChange } = props;

return (

<div>

{options.map((opt) => {

return (

<div

onClick={() => {

onChange(opt);

}}

>

{opt.label}

</div>

);

})}

</div>

);

};

import { Option } from './WithoutForwardRef';

interface WithForwardRefProps<OptionType> {

onChange: (option: OptionType) => void;

options: OptionType[];

}

export const WithForwardRef = React.forwardRef(

<OptionType extends Option>(

props: WithForwardRefProps<OptionType>,

ref?: React.Ref<HTMLDivElement>,

) => {

const { options, onChange } = props;

return (

<div>

{options.map((opt) => {

return (

<div

onClick={() => {

onChange(opt);

}}

>

{opt.label}

</div>

);

})}

</div>

);

},

);

import { WithoutForwardRef, Option } from './WithoutForwardRef';

import { WithForwardRef } from './WithForwardRef';

interface CustomOption extends Option<number> {

action: (value: number) => void;

}

const App: React.FC = () => {

return (

<div>

<h3>Without Forward Ref</h3>

<h4>Basic</h4>

<WithoutForwardRef

options={[{ value: 'test', label: 'Test' }, { value: 1, label: 'Test Two' }]}

onChange={(option) => {

// Does type inference on the type of value in the options

console.log('BASIC', option);

}}

/>

<h4>Custom</h4>

<WithoutForwardRef<CustomOption>

options={[

{

value: 1,

label: 'Test',

action: (value) => {

console.log('ACTION', value);

},

},

]}

onChange={(option) => {

// Intellisense works here

option.action(option.value);

}}

/>

<h3>With Forward Ref</h3>

<h4>Basic</h4>

<WithForwardRef

options={[{ value: 'test', label: 'Test' }, { value: 1, label: 'Test Two' }]}

onChange={(option) => {

// Does type inference on the type of value in the options

console.log('BASIC', option);

}}

/>

<h4>Custom (WitForwardRef is not generic here)</h4>

<WithForwardRef<CustomOption>

options={[

{

value: 1,

label: 'Test',

action: (value) => {

console.log('ACTION', value);

},

},

]}

onChange={(option) => {

// Intellisense SHOULD works here

option.action(option.value);

}}

/>

</div>

);

};

在中App.tsx,它表示该WithForwardRef组件不是通用的。有没有办法做到这一点?

回购示例:https :

//github.com/jgodi/generics-with-forward-

ref

谢谢!

回答:

创建通用组件作为输出React.forwardRef是不能直接1(见底部进一步信息)。不过,还有其他选择-让我们简化示例以进行说明:

type Option<O = unknown> = {

value: O;

label: string;

}

type Props<T extends Option<unknown>> = { options: T[] }

const options = [

{ value: 1, label: "la1", flag: true },

{ value: 2, label: "la2", flag: false }

] // just some options data

1.投放

// Given input comp for React.forwardRef

const FRefInputComp = <T extends Option>(props: Props<T>, ref: Ref<HTMLDivElement>) =>

<div ref={ref}> {props.options.map(o => <p>{o.label}</p>)} </div>

// Cast the output

const FRefOutputComp1 = React.forwardRef(FRefInputComp) as

<T extends Option>(p: Props<T> & { ref?: Ref<HTMLDivElement> }) => ReactElement

const Usage11 = () => <FRefOutputComp1 options={options} ref={myRef} />

// options has type { value: number; label: string; flag: boolean; }[]

// , so we have made FRefOutputComp generic!

forwardRef之所以有效,是因为原则上返回类型是一个普通函数。我们只需要一个通用函数类型形状。您可以使用其他类型来简化断言:

type ForwardRefFn<R> = <P = {}>(p: P & React.RefAttributes<R>) => ReactElement | null

// RefAttributes is built-in with ref and key props defined

const Comp12 = React.forwardRef(FRefInputComp) as ForwardRefFn<HTMLDivElement>

const Usage12 = () => <Comp12 options={options} ref={myRef} />

2.包起来

const FRefOutputComp2 = React.forwardRef(FRefInputComp)

// T is replaced by its constraint Option<unknown> in FRefOutputComp2

export const Wrapper = <T extends Option>({myRef, ...rest}:

Props<T> & {myRef: React.Ref<HTMLDivElement>}) => <FRefOutputComp2 {...rest} ref={myRef} />

const Usage2 = () => <Wrapper options={options} myRef={myRef} />

3.忽略它(使用自定义ref prop)

这是我最喜欢的-最简单的替代方法,在React中是合法的方法,并且不使用forwardRef

const Comp3 = <T extends Option>(props: Props<T> & { myRef: Ref<HTMLDivElement> }) =>

<div ref={myRef}> {props.options.map(o => <p>{o.label}</p>)} </div>

const Usage3 = () => <Comp3 options={options} myRef={myRef} />


1的类型声明的React.forwardRef为:

function forwardRef<T, P = {}>(render: ForwardRefRenderFunction<T, P>): ...

因此,它采用了类似组件的通用接口,其类型参数T,P

必须 是具体的。换句话说:ForwardRefRenderFunction不是 一个普通的

函数

声明,所以高阶函数类型推断 不能

在调用函数传播自由型参数React.forwardRef


操场

以上是 使用Typescript进行反应—使用React.forwardRef时的泛型 的全部内容, 来源链接: utcz.com/qa/435277.html

回到顶部