在与 React 和 TypeScript 中的类型和 forwardRefs 斗争了一段时间之后,我希望其他人可以为我解决这个问题。
我正在构建一个 DataList 组件,它由三部分组成:
- 容纳所有事件侦听器和逻辑的容器
- 列出自己,一个
ul
- 列表项,一个
li
最终,用法将如下所示:
<DataList.List ...>
<DataList.Item ...>content</DataList.Item>
</DataList.List>
为了实现我需要的功能,我使用了 React.forwardRef,但是我发现使用 TypeScript 很难做到这一点,因为我很难正确键入组件来接收 aref
和children
额外的 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; }'.