reactjs - React-underkomponenter i Typescript
Vi har noen komplekse sammensetninger av komponenter, og jeg har problemer med å gjøre dem typesikre. Basert på koden nedenfor, ville jeg forventet at Typescript kunne gi typer for Menu.Item eller Menu.Link, men det gjør den ikke av en eller annen grunn, de blir inferert som "any" (som blir raffinert til JSX.Element<any> når du pakker det inn i JSX). Har du noen idé om hvorfor dette skjer?
import * as React from 'react';
type RootFunctionComponent<OwnProps, SubComponents> = React.FunctionComponent<OwnProps> & SubComponents;
interface ItemProps {
text: string;
};
interface LinkProps {
href: string;
}
const Item: React.FunctionComponent<ItemProps> = props => <div {...props} />;
const Link: React.FunctionComponent<LinkProps> = props => <div {...props} />;
interface MenuSubComponents {
Item: React.FunctionComponent<;
Link: typeof Link;
}
const Menu: React.FunctionComponent<{}, MenuSubComponents> & MenuSubComponents = props => <div {...props} />
Menu.Item = Item;
Menu.Link = Link;
const Test: React.FunctionComponent<{}> = () => {
return <>
<Menu>
<Menu.Item text={false} />
<Menu.Link />
</Menu>
</>
}
Resultat :
Svar #1
Problemet var med menytypenes definisjoner:
React.FC<{}, MenuSubComponents>
Korrekt bruk er:
React.FC<MenuSubComponents>
Du kan se dette i aksjon her: https://codesandbox.io/s/condescending-lamarr-xjkcw
Svar #2
Her er et komplett eksempel på en Higher Order Component-tabell med props
import React from 'react'
import { tw } from 'twind'
import Body from './Body'
import Cell from './Cell'
import Head from './Head'
import Row from './Row'
export type CommonPropsType = {
className?: string
children: React.ReactNode
}
type TableSubComponents = {
Row: typeof Row
Cell: typeof Cell
Head: typeof Head
Body: typeof Body
}
type TablePropsType = CommonPropsType & { wrapperClassName?: string }
const Table: React.FunctionComponent<TablePropsType> & TableSubComponents = (
props: TablePropsType
) => {
const { className, children, wrapperClassName } = props
return (
<div className={tw('overflow-x-auto pb-2', wrapperClassName)}>
<table
className={tw('min-w-full leading-normal', className)}
cellPadding="8">
{children}
</table>
</div>
)
}
Table.Row = Row
Table.Cell = Cell
Table.Head = Head
Table.Body = Body
export default Table