簡體   English   中英

如何為 Material UI ListItem 鍵入道具?

[英]How to type props for Material UI ListItem?

我正在嘗試編寫一個包裝器組件,該組件將決定是否讓ListItem呈現react-router-dom Linkbutton

// 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM