如何制作一个具有泛型类型的函数式 React 组件?

Jeg*_*ggy 33 typescript reactjs tsx typescript-generics

我正在尝试制作一个 React 组件,它接受一个通用类型参数,该参数将成为其 prop 类型的一部分。

我想要一个看起来像这样的解决方案:

interface TestProps<T> {
  value: T;
  onChange: (newValue: T) => void;
}

const Test: React.FC<TestProps<T>> = (props) => (
  <span>{props.value}</span>
);
Run Code Online (Sandbox Code Playgroud)

我已经看到 TypeScript 2.9 中对此有支持,而我使用的是 4.3.5。

它的用法如下:

const Usage: React.FC = () => (
  <div>
    <Test<Obj>
      value={{ name: 'test' }}
      onChange={(newValue) => {
        console.log(newValue.name);
      }}
    />
  </div>
);
Run Code Online (Sandbox Code Playgroud)

代码沙箱:https://codesandbox.io/s/react-typescript-playground-forked-8hu13?file=/src/ index.tsx

cap*_*ian 31

您需要Test以这种方式重写您的组件

const Test= <T,>(props:TestProps<T>) => (
    <span>Some component logic</span>
);
Run Code Online (Sandbox Code Playgroud)

你能用 React.FC<TestProps> 显示同样的结果吗?这是不可能的FC

这是FC实现:

interface FunctionComponent<P = {}> {
  (props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
  // ... other static properties
}
Run Code Online (Sandbox Code Playgroud)

您可能已经注意到,FC是函数类型,而不是 props 类型。

更新

您可以创建更高阶的函数,但我不确定它是否值得

const WithGeneric = <T,>(): React.FC<TestProps<T>> =>
  (props: TestProps<T>) => (
    <span>Some component logic</span>
  );
const Test = WithGeneric<Obj>()
Run Code Online (Sandbox Code Playgroud)

  • 进行了更新。用“FC”是不可能的 (2认同)

AKX*_*AKX 30

最简单的方法是使通用 FC 成为常规函数,而不是箭头函数。(React.PropsWithChildren<>模拟React.FC对您的props类型的影响。)

function Test<T>(props: React.PropsWithChildren<TestProps<T>>) {
    return <span>Some component logic</span>;
}
Run Code Online (Sandbox Code Playgroud)


Ame*_*icA 15

就我而言,它类似于以下代码:

export interface FormProps<T> {
  validator?: AnyObjectSchema;
  onSubmit?: (data: T) => void;
}

const Form = <T = any,>({
  children,
  validator,
}: PropsWithChildren<FormProps<T>>): JSX.Element => {
  ~~~
Run Code Online (Sandbox Code Playgroud)

并在使用中:

type MyType = ...

<Form<MyType>
  validation={something}
  onSubmit={handleSomething}
>
  <SomeCompo />
  <AnotherSomeCompo />
</Form>
Run Code Online (Sandbox Code Playgroud)