reactjs - 如何为 Material UI ListItem 输入 props?

标签 reactjs typescript material-ui

我正在尝试编写一个包装器组件来决定是否拥有 ListItem渲染一个react-router-dom链接或一个按钮

// 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 prop 定义 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;

关于reactjs - 如何为 Material UI ListItem 输入 props?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62987470/

相关文章:

javascript - 在 react-native 中我们使用 styleSheet.create。我们在reactjs中使用什么?

angular - 为什么在 typescript 的 const 中使用带有 ${ 的反勾

javascript - 如何以 Angular 对html表的每一行进行组件化

typescript - 是否可以选择严格传播对象?

css - 使用 styled-components 动画背景渐变

reactjs - 如何为 JSXTransformer 正确包装几个 TD 标签?

javascript - 在reactjs中更新状态索引的问题

reactjs - 为什么 Tailwind 类在我的 Vite React 项目中没有生效?

reactjs - Material 表 react 。如何使表格标题和标题具有粘性

css - 无法让 justifyContent 与 flexbox 和 material ui 一起工作