0

在与 React 和 TypeScript 中的类型和 forwardRefs 斗争了一段时间之后,我希望其他人可以为我解决这个问题。

我正在构建一个 DataList 组件,它由三部分组成:

  • 容纳所有事件侦听器和逻辑的容器
  • 列出自己,一个ul
  • 列表项,一个li

最终,用法将如下所示:

<DataList.List ...>
  <DataList.Item ...>content</DataList.Item>
</DataList.List>

为了实现我需要的功能,我使用了 React.forwardRef,但是我发现使用 TypeScript 很难做到这一点,因为我很难正确键入组件来接收 arefchildren额外的 props。

DataListContainer
我本质上希望这个组件只处理逻辑和事件侦听器,同时返回主要的 DataList 组件(如下所示)。但这里的关键是我需要在这里创建 DataList ref 并将其分配给返回的组件。

const DataListContainer: React.FC = ({ children }) => {
  const listRef = useRef<HTMLUListElement>(null);

  return (
      <DataList ref={listRef}>{children}</DataList>
  );
};

DataList
我希望 DataList 组件只处理它的 UI 和道具。

interface Props extends TestId {
  focusedItemId?: string;
}

const DataList: React.FC<Props> = React.forwardRef<HTMLUListElement, Props>(
  ({ children, focusedItemId, testId }, ref) => {
    return (
      <ul
        aria-activedescendant={focusedItemId}
        data-test-id={testId}
        ref={ref}
      >
        {children}
      </ul>
    );
  },
);

不过,这并不完全正确。因为这个设置给了我错误

Type '{ children: any[]; ref: RefObject<HTMLUListElement>; }' is not assignable to type 'IntrinsicAttributes & Props & { children?: ReactNode; }'.
  Property 'ref' does not exist on type 'IntrinsicAttributes & Props & { children?: ReactNode; }'.
4

1 回答 1

2

你快到了!在React TypeScript Cheatsheet之后,问题出在DataList道具上。添加儿童道具将解决它

interface Props extends TestId {
  children?: ReactNode;
  focusedItemId?: string;
}

我在这个 CodeSandbox中重新创建了一个简单的示例

于 2021-03-06T09:42:48.370 回答