相当于React.memo的Typescript通用类

时间:2019-08-13 12:05:02

标签: reactjs typescript generics memo

有什么方法可以在React.memo中设置新的泛型吗?

例如,对于类组件,我可以使用

// set generic
class GenericClass<G extends string | number> extends PureComponent {}

// and use like this
<GenericClass<number> />

在以下情况下,我要使G型成为通用类型。

type G = string;
const MemoComponent = memo<{ value: G; onValueChange: (newValue: G) => void }>(
  ({ value, onValueChange }) => {
    return (
      <select
        onClick={() => {
          // do calculation
          onValueChange(value);
        }}
      >
        Button
      </button>
    );
  }
);

我想知道也可以在React.memo中设置泛型吗?例如,如下所示

const MemoComponent = <G extends string | number | object>React.memo<{value: G}>(({value}) => component)

// and use like this
<MemoComponent<number> />

2 个答案:

答案 0 :(得分:15)

我遇到了同样的问题,并像这样解决了。

    interface ISomeComponentWithGenericsProps<T> { value: T; } 

    function SomeComponentWithGenerics<T>(props: ISomeComponentWithGenericsProps<T>) {
      return <span>{props.value}</span>;
    }

    export default React.memo(SomeComponentWithGenerics) as typeof SomeComponentWithGenerics;

答案 1 :(得分:2)

更新(贷记到@ Ryan1729的问题提示):

tl; dr:

当前not possiblegeneric type arguments结合使用React.memo。 TypeScript无法保留传入的泛型组件(本质上是一个功能接口)的免费泛型类型参数,因此在调用React.memo时,我们必须提供一个具体的参数。

说明:

该问题的一般示例在above issue中给出:

function identity<T>(arg: T) { return arg; }
function memoize<F extends (...args: unknown[]) => unknown>(fn: F): F { return fn; }

// memid: unknown => unknown
// desired: memid<T>(T) => T
const memid = memoize(identity);

现在,当您查看React.memo的类型签名时,您会发现它是一个HOC,它返回某种内部Component类型,并带有由您的props产生的泛型类型参数。输入组件:

// Component: SFC<P> and NamedExoticComponent<P> are nothing more than 
// functional generic interfaces, we can interpret `React.memo` as a 
// generic higher order function.

function memo<P extends object>(Component: SFC<P>, ...): NamedExoticComponent<P>;

interface ExoticComponent<P = {}> {
  ...
  (props: P): (ReactElement|null);
  ...
}

不幸的是,TypeScript无法保留由SFC<P>产生的自由类型参数:

const Comp = <T extends {}>(props: {foo: T}) => {...};
// we do not provide concrete type parameter for Comp
const HOC = React.memo(Comp);
// doesn't work :/
const App = <HOC<string> />;

替代

1。)如果确实需要,可以将memo包装在另一个HOC中,但是不能在JSX中设置通用类型参数。

type MemoComponentProps<G> = { ... }

const createMemoComponent = <G extends string | number | object>() =>
  React.memo((props: MemoComponentProps<G>) => { ... })

const MemoComponent = createMemoComponent<number>();

2。)不要使用React.memo并切换到useMemo钩在输入组件内部。