简体   繁体   English

带有 forwardRef 的 JSX 点符号 typescript

[英]JSX dot notation with forwardRef typescript

I am trying to figure out the types for Dot Notation components with forwardRef.我正在尝试使用 forwardRef 找出 Dot Notation 组件的类型。

So I found this example which perfectly illustrates how I currently use dot notation, but doesn't include forwardRef: https://codesandbox.io/s/stpkm所以我发现这个例子完美地说明了我目前如何使用点符号,但不包括 forwardRef: https://codesandbox.io/s/stpkm

This is what I'm trying to achieve, but can't figure out the typings.这就是我想要实现的目标,但无法弄清楚类型。

import { forwardRef, useImperativeHandle } from "react";
//
import { ForwardRefRenderFunction } from "react";

const TabToggle: React.FC = () => null;
const TabContent: React.FC = () => null;

interface TabsStatic {
  Toggle: typeof TabToggle;
  Content: typeof TabContent;
}

export interface TabsProps {
  initialIndex?: number;
}

export interface TabsRefMethods {
  show: () => null;
  hide: () => null;
}

export const Tabs: React.ForwardRefRenderFunction<
  TabsRefMethods,
  TabsProps & TabsStatic
> = forwardRef((props, ref) => {
  const openFn = () => null;
  const closeFn = () => null;
  useImperativeHandle(ref, () => ({ show: openFn, hide: closeFn }));
  return null;
});

Tabs.Toggle = TabToggle;
Tabs.Content = TabContent;

Code Sandbox Demo : https://codesandbox.io/s/jsx-dot-notation-in-typescript-with-react-forked-38e1z?file=/src/Tabs.tsx代码沙盒演示https://codesandbox.io/s/jsx-dot-notation-in-typescript-with-react-forked-38e1z?file=/src/Tabs.tsx

There are two possible approaches I'm aware of and have used.我知道并使用了两种可能的方法。 Both have slightly different tradeoffs.两者的权衡略有不同。

The first is to interset ( & ) the static components and mark them as optional ( Partial ) so that there isn't an error when declaring the component.第一个是插入 ( & ) static 组件并将它们标记为可选 ( Partial ) 以便在声明组件时不会出错。 The downside is that they are denoted as optional even though they are always set.缺点是它们被表示为可选的,即使它们总是被设置。

import * as React from "react";

const TabToggle: React.FC = () => null;
const TabContent: React.FC = () => null;

interface TabsStatic {
  Toggle: typeof TabToggle;
  Content: typeof TabContent;
}

export interface TabsProps {
  initialIndex?: number;
}

export interface TabsRefMethods {
  show: () => null;
  hide: () => null;
}

export const Tabs: React.ForwardRefExoticComponent<
  React.PropsWithoutRef<TabsProps> & React.RefAttributes<TabsRefMethods>
> &
  Partial<TabsStatic> = React.forwardRef((props, ref) => null);

Tabs.Toggle = TabToggle;
Tabs.Content = TabContent;

The alternative is to make them required, but this requires a cast.另一种方法是使它们成为必需的,但这需要强制转换。 The resulting type is more accurate, but it does require a cast.结果类型更准确,但它确实需要强制转换。

type TabsComponent = React.ForwardRefExoticComponent<
  React.PropsWithoutRef<TabsProps> & React.RefAttributes<TabsRefMethods>
> &
  TabsStatic;

export const Tabs = React.forwardRef((props, ref) => null) as TabsComponent;

Tabs.Toggle = TabToggle;
Tabs.Content = TabContent;

There is much easier way to achieve the same result:有更简单的方法可以达到相同的结果:

const Flex = React.forwardRef(function Flex(...) {
  ...
})

const FlexRow = React.forwardRef(...)
const FlexColumn = React.forwardRef(...)

const FlexNamespace = Object.assign(Flex, {Row: FlexRow, Column: FlexColumn})

export {FlexNamespace as Flex}

Now you can use Flex , Flex.Row , and Flex.Column with TS being happy.现在您可以在 TS 满意的情况下使用FlexFlex.RowFlex.Column The magic line is Object.assign which does not cause the same type issue as Flex.Row = FlexRow does.魔术线是Object.assign不会导致与Flex.Row = FlexRow相同的类型问题。 Don't ask me why, I just accidentally found this不要问我为什么,我只是偶然发现了这个

Or even shorter:或者更短:

const TabsComponent = () => {
  // implement the Tabs component
};

const TabContentComponent = () => {
  // implement the TabContent component
};

const TabToggleComponent = () => {
  // implement the TabToggle component
};

export const Tabs = Object.assign(forwardRef(TabsComponent),
  // a component with forward refs
  TabContent: forwardRef(TabContentComponent),

  // a component without forwarding
  TabToggle
};

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

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