【问题标题】:Typescript: How to type React abstract components?Typescript:如何键入 React 抽象组件?
【发布时间】:2020-03-23 09:23:06
【问题描述】:

我在尝试在 Typescript 中键入抽象组件时遇到问题(来自大量流程经验。) - 以下示例使用的是 Typescript 3.8.3

代码是:

const useSlot = (): [React.ReactNode, React.ComponentType] => {
    const slotRef = useRef();
    const Slot = ({ children }: { children: React.ReactNode }): React.ReactNode =>
        slotRef.current ? createPortal(children, slotRef.current) : null;

    return [<div ref={slotRef} />, Slot];
};

export default useSlot;

而用法是:

const [slotLocation, Slot] = useSlot();

return (
    <div>
        {slotLocation}
        <Slot>Some content</Slot>
    </div>
);

我遇到的问题是我在网上找不到任何通用的 React 组件类型...在流程中,我们将使用 React.AbstractComponent&lt;Props&gt; 类型来涵盖任何类型的 React 组件。但我在 Typescript 中找不到替代方案,我见过 React.ComponentReact.FCReact.ComponentType;但他们都没有工作。显然它不允许从这些组件类型返回ReactNode(特别是string)。

error TS2345: Argument of type 'ReactNode' is not assignable to parameter of type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<any, any, any>)>'.
  Type 'string' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<any, any, any>)>'.

20         render(slotLocation)
                  ~~~~~~~~~~~~

error TS2322: Type '({ children }: { children: React.ReactNode; }) => React.ReactNode' is not assignable to type 'ComponentType<{}>'.
  Type '({ children }: { children: React.ReactNode; }) => React.ReactNode' is not assignable to type 'FunctionComponent<{}>'.
    Type 'ReactNode' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<any, any, any>)>'.
      Type 'string' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<any, any, any>)>'.

12     return [<div ref={slotRef} />, Slot];

我们如何键入一个可以返回任何类型的 React 节点的通用组件类型?

【问题讨论】:

  • 最通用的类​​型是JSX.Element
  • @RobCo JSX.ElementReactNode 相同;它是一个渲染节点。在这种情况下,我想返回一个我们需要调用才能渲染的 React 组件;例如&lt;Slot /&gt;&lt;div&gt;{slot}&lt;/div&gt;。使用JSX.Element,我们得到这个错误JSX element type 'Slot' does not have any construct or call signatures.(因为它不是可调用的。)

标签: reactjs typescript


【解决方案1】:

首先您需要输入ref 以将其传递给createPortal

第二个Slot的返回类型是ReactPortal而不是ComponentType

你还应该让 TypeScript 尽可能多地推断,只键入 TypeScript 无法推断的内容

我返回数组as const 来输入元素的位置,而不是显式输入useSlot 的返回类型

const useSlot = () => {
  const slotRef = useRef<HTMLDivElement>(null)
  const Slot = ({ children }: { children: React.ReactNode }) =>
    slotRef.current ? createPortal(children, slotRef.current) : null

  return [<div ref={slotRef} />, Slot] as const
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-03
    • 1970-01-01
    • 2021-06-18
    • 2021-07-28
    • 2021-03-08
    • 2014-10-03
    • 2020-05-06
    • 2017-09-06
    相关资源
    最近更新 更多