Material-ui: 转换与React-Router兼容的ListItem

创建于 2017-08-30  ·  21评论  ·  资料来源: mui-org/material-ui

我想将List中的每个ListItem List转换为Link组件。

我有一个由Drawer组件组成的List组件,
该列表由4个ListItem s组成。
我想要实现的是将每个ListItem转换为React路由器Link
我试图修改抽屉的onClick方法,获取被单击的ListItem的ID,然后根据ID以编程方式更改窗口的位置。
但是我确实认为这种方法比react概念更令人费解。
我也尝试添加Linkcomponent的道具ListItem ,但它造成的错误。(我已经看到你已经使用了在component的道具docs)。
达到此要求的推荐方法是什么?

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Drawer from 'material-ui/Drawer';
import List, { ListItem, ListItemIcon, ListItemText } from 'material-ui/List';
import Face from 'material-ui-icons/Face';
import Person from 'material-ui-icons/Person';
import Assignment from 'material-ui-icons/Assignment';
import Link from 'react-router-dom/Link';
import { FormattedMessage } from 'react-intl';

const styles = {
   list: {
      width: 250,
      flex: 'initial',
    },
};

 class UndockedDrawer extends Component {

   constructor() {
      super();
      this.onClick = this.onClick.bind(this);
    }

    onClick(e, data) {
       console.log(data);
       this.props.onRequestClose();
     }

   render() {
       const classes = this.props.classes;
        const sidebarListItems = (
     <div>
         <ListItem button >
            <ListItemIcon>
               <Person />
           </ListItemIcon>
            <ListItemText primary={<FormattedMessage id="user" />} />
          </ListItem>
    <ListItem button>
      <ListItemIcon>
        <Assignment />
      </ListItemIcon>
      <ListItemText primary={<FormattedMessage id="consultant" />} />
    </ListItem>
    <ListItem button>
      <ListItemIcon>
        <Face />
      </ListItemIcon>
      <ListItemText primary={<FormattedMessage id="student" />} />
    </ListItem>
  </div>
);

const sidebarList = (
  <div>
    <List className={classes.list} >
      {sidebarListItems}
    </List>
  </div>
);

return (
  <div>
    <Drawer
      anchor="right"
      open={this.props.open}
      onRequestClose={this.props.onRequestClose}
      onClick={this.onClick}
    >
      {sidebarList}
    </Drawer>
   </div>
   );
   }
 }

  UndockedDrawer.propTypes = {
     classes: PropTypes.shape({}).isRequired,
     open: PropTypes.bool.isRequired,
     onRequestClose: PropTypes.func.isRequired,
    };

   export default withStyles(styles)(UndockedDrawer);
  • Material-UI:1.0.6-beta
  • 反应:^ 15.6.1
  • 浏览器:Chrome:60
  • react-router-dom:^ 4.1.2
question

最有用的评论

在文档中对此进行了介绍: https: //material-ui.com/components/buttons/#third -party-routing-library。

import React from 'react';
import { MemoryRouter as Router } from 'react-router';
import { Link, LinkProps } from 'react-router-dom';
import ListItem from '@material-ui/core/ListItem';
import { Omit } from '@material-ui/types';

// The usage of React.forwardRef will no longer be required for react-router-dom v6.
// see https://github.com/ReactTraining/react-router/issues/6056
const AdapterLink = React.forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => (
  <Link innerRef={ref as any} {...props} />
));

const CollisionLink = React.forwardRef<HTMLAnchorElement, Omit<LinkProps, 'innerRef' | 'to'>>(
  (props, ref) => <Link innerRef={ref as any} to="/getting-started/installation/" {...props} />,
);

export default function ButtonRouter() {
  return (
    <Router>
      <ListItem color="primary" component={AdapterLink} to="/">
        Simple case
      </ListItem>
      <ListItem component={CollisionLink}>Avoids props collision</ListItem>
    </Router>
  );
}

所有21条评论

我想通了,我可以将ListItem包裹在Link ,如下所示:

<Link to="users" style={{ textDecoration: 'none' }}>
      <ListItem button >
        <ListItemIcon>
          <Person />
        </ListItemIcon>
        <ListItemText primary={<FormattedMessage id="user" />} />
      </ListItem>
    </Link>

通过这种方法,也会触发onClick方法。
有什么建议或改进吗?

我想通了,我可以将ListItem包装在Link中,如下所示

该解决方案在语义上无效。 看一下我们如何处理文档上的问题:

https://github.com/callemall/material-ui/blob/92bd073015b9cc0dff3a26195fcb49153ddaab78/docs/src/modules/components/AppDrawerNavItem.js#L71 -L83

你也可以试试这个

https://github.com/callemall/material-ui/blob/92bd073015b9cc0dff3a26195fcb49153ddaab78/docs/src/pages/demos/buttons/FlatButtons.js#L40 -L42

在文档中对此进行了介绍: https: //material-ui.com/components/buttons/#third -party-routing-library。

import React from 'react';
import { MemoryRouter as Router } from 'react-router';
import { Link, LinkProps } from 'react-router-dom';
import ListItem from '@material-ui/core/ListItem';
import { Omit } from '@material-ui/types';

// The usage of React.forwardRef will no longer be required for react-router-dom v6.
// see https://github.com/ReactTraining/react-router/issues/6056
const AdapterLink = React.forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => (
  <Link innerRef={ref as any} {...props} />
));

const CollisionLink = React.forwardRef<HTMLAnchorElement, Omit<LinkProps, 'innerRef' | 'to'>>(
  (props, ref) => <Link innerRef={ref as any} to="/getting-started/installation/" {...props} />,
);

export default function ButtonRouter() {
  return (
    <Router>
      <ListItem color="primary" component={AdapterLink} to="/">
        Simple case
      </ListItem>
      <ListItem component={CollisionLink}>Avoids props collision</ListItem>
    </Router>
  );
}

我在文档中没有看到它:
https://material-ui-next.com/demos/lists/
https://material-ui-next.com/demos/drawers/

这在使用React Router时很常见,但尚不清楚如何在ListItem使用NavLink ListItem
一个Buttoncomponent道具?
而且按钮道具和组件道具在同一个JSX标签上混合在一起吗?
这种混合是什么?
为什么这么复杂?

当使用@mehrdaad的解决方案时,链接看起来像普通的MUI列表,但是当使用component={Link}作为@oliviertassinari建议时,样式会混乱:
(在图像中,鼠标悬停在“ Build”上,但是第二项获得了下划线...)

screen shot 2017-11-16 at 12 09 05

@ilyador此UI链接样式问题已解决。

@ zhangwei900808不,在语义上还是错误的,它会生成<ul><a ..>...
https://codesandbox.io/s/lpwq74p30m

只需使用上面提供的答案

@oliviertassinari是否会有更简单的方法:

const styles = {
    li: {
        '&:hover': {
            backgroundColor: 'transparent',
        },
    },
};
// ...
<MenuItem disableGutters className={classes.li}>
    <Button component={Link} to="/logout" ...

为避免出现双重悬停效果,请在MenuItemButton (它们仍然有少量装订线/填充,这是另一个问题)
因为这很麻烦

演示: https : component={Link} to="/..."但这是相同的)

@caub为什么要引入一个额外的Button组件? 您可以在MenuItem上使用component属性。

@oliviertassinari,因为ul > a无效html5 https://codesandbox.io/s/lpwq74p30m

@caub nav > a有效。

好的,谢谢,很好https://codesandbox.io/s/lpwq74p30m

这是解决我的问题的解决方案

<List>
        {menus.map((menu: any, index: any) => {
          return (
            <ListItem
              key={index}
              {...{ to: menu.link }}
              component={Link}
              button={true}
            >
              <ListItemIcon>{menu.icon}</ListItemIcon>
              <ListItemText primary={menu.text} />
            </ListItem>
          );
        })}
      </List>

因此,只需将ListItem用作
键= {索引}
** {... {至:menu.link}} **
组件= {链接}
button = {true}
>

import {Link} from 'react-router-dom'

<ListItem component={Link} to="/" button>

// or
<ListItem component={props => <Link to="/" {...props} />} button>

@mehrdaad @oliviertassinari工作了^ _ ^

这对我来说是完美的。 谢谢!

投票最多的答案在MUI v4迁移后失败(我在4.3.1上),原因是“无法为功能组件提供引用。尝试访问该引用将失败。您是要使用React.forwardRef()吗?”

我已经将NavLink组件替换为包装器,如下所示:

import React, { Component } from "react"
import { NavLink } from "react-router-dom"

/**
 * React Router Nav Link wrapper to forward the ref to fix "Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?"
 *
 * From https://material-ui.com/guides/composition/#caveat-with-refs
 */
class NavLinkMui extends Component {
    render() {
        const { forwardedRef, ...props } = this.props
        return <NavLink {...props} ref={forwardedRef} />
    }
}

export default NavLinkMui

用法:

<ListItem
    button
    component={NavLinkMui}
    to='/'
>
    <ListItemIcon>
        <SlideshowIcon />
    </ListItemIcon>
</ListItem>

@HugoGresse是的,您需要使用前向引用API。 您应该能够在文档中找到示例。 我已经使用最新答案更新了https://github.com/mui-org/material-ui/issues/7956#issuecomment -326908167。 让我们知道是否可以。

@oliviertassinari它做到了。

我仍然对forwardRef解决方案或组件一有一些问题,其中Button文本颜色未考虑主题调色板颜色。 文字颜色应为白色,以匹配palette.type: 'dark' ,但为白色。

可能与MUI的更改有关,因为没有component道具,我仍然遇到问题。
Capture d'écran 2019-08-06 16 54 51

对于在这里阅读的人,可以将其他道具传递给ListItemText ...

<ListItemText
    primaryTypographyProps={{
        color: 'textPrimary'
    }}
    primary="Dashboard"
/>

顺便说一句,您的示例现在在TS中。

这是解决我的问题的解决方案

<List>
        {menus.map((menu: any, index: any) => {
          return (
            <ListItem
              key={index}
              {...{ to: menu.link }}
              component={Link}
              button={true}
            >
              <ListItemIcon>{menu.icon}</ListItemIcon>
              <ListItemText primary={menu.text} />
            </ListItem>
          );
        })}
      </List>

因此,只需将ListItem用作
键= {索引}
** {... {至:menu.link}} **
组件= {链接}
button = {true}
>

button={true}只是使抽屉的UI行为与没有链接相同。

对于尝试在Typescript中执行此操作的其他人:

使用ListItem组件属性指定一个简单示例元素作为ListItem实现。 Typescript中的技巧是在ListItem的道具上使用传播运算符(...)来越过不必要的和不需要的Typescript错误,这些错误为ListItem指定这种类型的组件和“ to”属性通常会带来(Typescript错误TS2769属性'component'在类型'IntrinsicAttributes ...上不存在)

import { NavLink } from "react-router-dom";

        <List>
            <ListItem button={true} {...{ component: NavLink, to: "/Somewhere" }}>
                <ListItemIcon>
                    <ShoppingCartIcon />
                </ListItemIcon>
                <ListItemText primary="Orders" />
            </ListItem>
        </List>

或者,如果您只想在ListItem上使用onClick函数,例如:


    <List>
        <ListItem button={true} {...{ onClick: () => alert("foo") }}>
            <ListItemIcon>
                <DashboardIcon />
            </ListItemIcon>
            <ListItemText primary="Dashboard" />
        </ListItem>
    </List>

```

这对我有用

const NavLinkMui = React.forwardRef((props, ref) => (
  <NavLink {...props} activeClassName="Mui-selected" ref={ref} />
))
<ListItem button component={NavLinkMui} to={to}>{text}</ListItem>

投票最多的答案在MUI v4迁移后失败(我在4.3.1上),原因是“无法为功能组件提供引用。尝试访问该引用将失败。您是要使用React.forwardRef()吗?”

我已经将NavLink组件替换为包装器,如下所示:

import React, { Component } from "react"
import { NavLink } from "react-router-dom"

/**
 * React Router Nav Link wrapper to forward the ref to fix "Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?"
 *
 * From https://material-ui.com/guides/composition/#caveat-with-refs
 */
class NavLinkMui extends Component {
    render() {
        const { forwardedRef, ...props } = this.props
        return <NavLink {...props} ref={forwardedRef} />
    }
}

export default NavLinkMui

用法:

<ListItem
    button
    component={NavLinkMui}
    to='/'
>
    <ListItemIcon>
        <SlideshowIcon />
    </ListItemIcon>
</ListItem>

谢谢@HugoGresse这工作得很好:-)

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

rbozan picture rbozan  ·  3评论

ryanflorence picture ryanflorence  ·  3评论

zabojad picture zabojad  ·  3评论

ghost picture ghost  ·  3评论

revskill10 picture revskill10  ·  3评论