简体   繁体   English

React.forwardRef 在流中具有通用的 Props 类型

[英]React.forwardRef with generic Props type in flow

I'm trying to add React.forwardRef to an already existing component that looks like this:我正在尝试将React.forwardRef添加到如下所示的现有组件中:

type Props<T> = {
  someProp: T,
}

const Component = <T>({someProp}: Props<T>) => {...}

Now this is component uses Props<T> , where T is some generic type.现在这是组件使用Props<T> ,其中T是某种通用类型。 I'm having difficulties adding React.forwardRef and having no errors and no compromises on typing.我在添加React.forwardRef遇到了困难,并且在打字时没有错误和妥协。

Here are some things I've tried:以下是我尝试过的一些事情:

// Complains T doesn't exist
const Component = React.forwardRef<Props<T>, HTMLElement>((props, ref) => {...})
// Multiple errors
type Props<T> = {
    value: T,
    onChange: T => void,
}

const ChildComponent = <T>() => React.forwardRef<Props<T>, HTMLDivElement>((props, ref) => {
    return <div ref={ref}>123</div>;
});

const ParentComponent = () => {
    const [value, setValue] = React.useState(123);
    const onChange = newValue => setValue(newValue);

    return <ChildComponent />;
};

===============================================================================================

All branches are incompatible:
 • Either inexact AbstractComponent [1] is incompatible with exact React.Element [2].
 • Or AbstractComponent [1] is incompatible with React.Portal [3].
 • Or property @@iterator is missing in AbstractComponent [1] but exists in $Iterable [4].

    ../x.jsx
       7│   onChange: T => void,
       8│ }
       9│
      10│ const ChildComponent = <T>() => **React.forwardRef<Props<T>, HTMLDivElement>((props, ref) => {
      11│   return <div ref={ref}>123</div>;
      12│ })**;
      13│
      14│ const ParentComponent = () => {
      15│   const [value, setValue] = React.useState(123);

     /private/tmp/flow/flowlib_1eb3ba5b/react.js
 [2]  18│   | React$Element<any>
 [3]  19│   | React$Portal
 [4]  20│   | Iterable<?React$Node>;
        :
 [1] 297│   ): React$AbstractComponent<Config, Instance>;

Do you know how to use forwardRef with generic types in flow?你知道如何在流中使用具有泛型类型的 forwardRef 吗?

Does something like this work for you?像这样的事情对你有用吗?

import React, { forwardRef } from 'react';

function GenericComponent<T>(props: { someProp: T }) {
  return null;
}

const ForwardedRefGenericComponent = forwardRef(
  (props, ref) => <GenericComponent ref={ref} {...props} />
);


function App() {
  // Examples of using ForwardedRefGenericComponent
  return (
    <div>
      <ForwardedRefGenericComponent someProp={42} />
      <ForwardedRefGenericComponent someProp={"abc"} />
      <ForwardedRefGenericComponent someProp={true} />
      <ForwardedRefGenericComponent someProp={["x", "y"]} />
      <ForwardedRefGenericComponent someProp={{ x: "y" }} />
    </div>
  );
}

Try Flow 尝试流程

Flow should be smart enough to infer the types for you so there's no need to declare the types explicitly for ForwardedRefGenericComponent . Flow 应该足够智能,可以为您推断类型,因此无需为ForwardedRefGenericComponent显式声明类型。

One time generic factory can make Flow happy一次通用工厂可以让 Flow 开心

/* @flow */

import React from 'react';

type Props<T> = {|
  someProp: T
|};

const withRef = <T>() => React.forwardRef<Props<T>, any>((props, ref) => {
  return (<div ref={ref} />);
});

const Component = withRef<string>();  

Perhaps this example of working code will help future readers on how to use forwardRef with other props in Typescript.也许这个工作代码示例将帮助未来的读者了解如何将 forwardRef 与 Typescript 中的其他道具一起使用。

const FancyInput = forwardRef<HTMLInputElement, InputHTMLAttributes<HTMLInputElement>>(
  (otherProps, ref) => (
    <input ref={ref} type="text" className="input bg-white py-1 px-2 w-48" {...otherProps} />
  ),
)

It's not exactly what you're asking for, but there is a work-around.这不完全是你所要求的,但有一个解决方法。 The flow docs about HOCs inspired me. 关于 HOC流程文档启发了我。 Instead of trying to export a component, export a generic component factory.与其尝试导出组件,不如导出通用组件工厂。 In the file where you want to use the component, create one or more concrete component instances with the factory.在要使用组件的文件中,使用工厂创建一个或多个具体组件实例。

// component definition file
export const createComponent = <T>(): React.AbstractComponent<Props<T>, HTMLElement> =>
  React.forwardRef<Props<T>, HTMLElement>((props, ref) => {...});

// file component is used in
import { createComponent } from './definition';
const ComponentT1 = createComponent<T1>();

const SomeComponent = (): MixedElement => {
  const ref = useRef();
  return <ComponentT1 ref={ref} />
};

The difference from the previous responses is that they use React function components, whereas this uses a plain JavaScript factory, that React doesn't know even existed.与之前的响应不同的是,他们使用 React 函数组件,而这使用了一个普通的 JavaScript 工厂,React 甚至不知道它存在。 It's not a very elegant work-around, but I hope it helps someone out.这不是一个非常优雅的解决方法,但我希望它可以帮助某人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM