[英]How to type props for Material UI ListItem?
我正在嘗試編寫一個包裝器組件,該組件將決定是否讓ListItem呈現react-router-dom Link
或button
// inside some component
let props
if ("uri" in navItem) {
props = { component: Link, to: navItem.uri }
} else {
props = { button: true, onClick: navItem.onClick }
}
return (
<ListItem {...props}>
...some more code ...
</ListItem
)
它抱怨ListItem
說沒有重載匹配這個調用。 我猜錯誤是因為沒有輸入props
變量。 但是,我無法理解如何輸入這個,這對於我的 TS 水平來說太復雜了。
我能得到一些關於如何輸入這些的指示嗎?
編輯:
要添加更多信息,我只是想把它干掉:
export type NavItem = Omit<BaseNavItem, 'onClick'> | Omit<BaseNavItem, 'uri'>;
type BaseNavItem = {
icon: React.ReactNode;
label: string;
uri: string;
onClick: () => void;
};
// MyComponent.tsx
// it will render Link or buttons depending
// on whether uri or onClick was passed in the navItem
if ("uri" in navItem) {
return (
<li>
<ListItem key={label} component={RouterLink} to={navItem.uri}>
<ListItemIcon>{icon}</ListItemIcon>
<ListItemText primary={label} />
</ListItem>
</li>
)
} else {
return (
<ListItem key={label} button onClick={navItem.onClick}>
<ListItemIcon>{icon}</ListItemIcon>
<ListItemText primary={label} />
</ListItem>
)
}
這是一個簡單的解決方案:
import React from "react";
import { ListItem, ListItemIcon, ListItemText } from "@material-ui/core";
import { Link } from "react-router-dom";
interface INavItem {
icon: React.ReactNode;
label: string;
// ? makes the prop optional
// it can be undefined
uri?: string;
onClick?: () => void;
}
interface Props {
navItem: INavItem;
}
function NavItem({ navItem }: Props) {
const Inner = (
<>
<ListItemIcon>{navItem.icon}</ListItemIcon>
<ListItemText primary={navItem.label} />
</>
);
if (navItem.uri) {
return (
<ListItem component={Link} to={navItem.uri}>
{Inner}
</ListItem>
);
}
return (
<ListItem button onClick={navItem.onClick}>
{Inner}
</ListItem>
);
}
export default NavItem;
至於根據component
道具定義props
,它要復雜得多,在這種情況下沒有必要。
檢查文檔: https://material-ui.com/guides/typescript/#usage-of-component-prop
例子:
import React, { ElementType } from "react";
import {
ListItem,
ListItemIcon,
ListItemText,
ListItemProps,
} from "@material-ui/core";
import { Link } from "react-router-dom";
import { People, Edit } from "@material-ui/icons";
interface INavItem {
icon: React.ReactNode;
label: string;
}
export type MyListItemProps<C extends ElementType> = ListItemProps<
C,
{ component?: C }
> &
INavItem;
function NavItem<C extends ElementType>({
icon,
label,
...props
}: MyListItemProps<C>) {
return (
<ListItem {...props}>
<ListItemIcon>{icon}</ListItemIcon>
<ListItemText primary={label} />
</ListItem>
);
}
const navItems = [
{ to: "/users", icon: People, label: "Users" },
{ icon: Edit, label: "Edit", onClick: () => {} },
];
// Usage
const Nav = () => {
return navItems.map(({ to, icon, label, onClick }) => {
if (to) {
return <NavItem<Link> to={to} icon={icon} label={label} />;
}
return <NavItem icon={icon} label={label} button onClick={onClick} />;
});
};
export default Nav;
或者
const navItems = [
{ to: "/users", icon: People, label: "Users" },
{ icon: Edit, label: "Edit", onClick: () => {}, button: true },
];
// Usage
const Nav = () => {
return navItems.map(({ to, ...props }) => {
if (to) {
return <NavItem<Link> to={to} {...props} />;
}
return <NavItem {...props} />;
});
};
export default Nav;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.