Ich möchte jedes ListItem
in einer List
zu einer Link
Komponente machen.
Ich habe eine Drawer
-Komponente, die aus einer List
-Komponente besteht.
Diese Liste besteht aus 4 ListItem
s.
Was ich erreichen möchte, ist, dass jedes ListItem
in einen React-Router Link
konvertiert wird.
Ich habe versucht, die onClick-Methode der Schublade zu ändern, die ID des angeklickten ListItem abzurufen und dann die Position des Fensters basierend auf der ID programmgesteuert zu ändern.
Aber ich denke, dieser Ansatz ist fragwürdiger als die Reaktionskonzepte.
Ich habe auch versucht, Link
zu component
prop in ListItem
hinzuzufügen, aber es kam zu einem Fehler. (Ich habe gesehen, dass Sie in component
prop in verwendet haben docs).
Was ist der empfohlene Weg, um diese Anforderung zu erreichen?
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);
Ich habe herausgefunden, dass ich ListItem
Link
wie folgt in
<Link to="users" style={{ textDecoration: 'none' }}>
<ListItem button >
<ListItemIcon>
<Person />
</ListItemIcon>
<ListItemText primary={<FormattedMessage id="user" />} />
</ListItem>
</Link>
Bei diesem Ansatz wird auch die onClick-Methode ausgelöst.
Anregungen oder Verbesserungen?
Ich habe herausgefunden, dass ich ListItem wie folgt in einen Link einbinden kann
Diese Lösung ist semantisch nicht gültig. Schauen Sie sich an, wie wir mit dem Problem in der Dokumentation umgehen:
Sie können diesen auch ausprobieren
Dies wird in der Dokumentation behandelt: 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>
);
}
Ich sehe es nicht in den Dokumenten:
https://material-ui-next.com/demos/lists/
https://material-ui-next.com/demos/drawers/
Dies ist eine häufige Sache bei der Verwendung von React Router, aber es ist nicht klar, wie NavLink
in einem ListItem
.
Ein Button
mit component
Prop?
Und die Button-Requisiten und die Komponenten-Requisiten werden auf demselben JSX-Tag zusammengemischt?
Was ist das für ein Mixin?
Warum so komplex?
Wenn Sie die Lösung von component={Link}
wie von @oliviertassinari vorgeschlagen, wird der Stil durcheinander gebracht:
(Im Bild schwebt die Maus über "Build", aber das zweite Element wird unterstrichen ...)
@ilyador Dieses Problem mit dem UI-
@ zhangwei900808 Nein, das ist semantisch immer noch falsch, es generiert <ul><a ..>...
https://codesandbox.io/s/lpwq74p30m
Verwenden Sie einfach die oben angegebene Antwort
@oliviertassinari Gibt es einen einfacheren Weg:
const styles = {
li: {
'&:hover': {
backgroundColor: 'transparent',
},
},
};
// ...
<MenuItem disableGutters className={classes.li}>
<Button component={Link} to="/logout" ...
Um einen Double-Hover-Effekt zu vermeiden, auf dem MenuItem
und auf Button
(die immer noch eine leichte Rinne / Polsterung haben, ein weiteres Problem)
Weil das umständlich ist
Demo: https://codesandbox.io/s/nk834yk5pl (ohne component={Link} to="/..."
aber das ist das gleiche)
@caub Warum führen Sie eine zusätzliche Button-Komponente ein? Sie können die Komponenteneigenschaft im MenuItem verwenden.
@oliviertassinari, weil ul > a
nicht gültig ist html5 https://codesandbox.io/s/lpwq74p30m
@caub nav > a
ist gültig.
Ok, danke, gut https://codesandbox.io/s/lpwq74p30m
Hier ist die Lösung, die mein Problem gelöst hat
<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>
Verwenden Sie daher einfach ListItem als
** {... {to: menu.link}} **
component = {Link}
button = {true}
>
import {Link} from 'react-router-dom' <ListItem component={Link} to="/" button> // or <ListItem component={props => <Link to="/" {...props} />} button>
@mehrdaad @oliviertassinari Es hat funktioniert ^ _ ^
Das war perfekt für mich. Vielen Dank!
Die am häufigsten gewählte Antwort schlug nach der Migration von MUI v4 (ich bin auf 4.3.1) aufgrund von "Funktionskomponenten können keine Refs zugewiesen werden. Versuche, auf diese Ref zuzugreifen, schlagen fehl. Wollten Sie React.forwardRef () verwenden?"
Ich habe die NavLink
-Komponente durch einen Wrapper wie folgt ersetzt:
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
Verwendung:
<ListItem
button
component={NavLinkMui}
to='/'
>
<ListItemIcon>
<SlideshowIcon />
</ListItemIcon>
</ListItem>
@HugoGresse Ja, Sie müssen die Forward-Ref-API verwenden. Beispiele sollten Sie in der Dokumentation finden können. Ich habe https://github.com/mui-org/material-ui/issues/7956#issuecomment -326908167 mit einer aktuellen Antwort aktualisiert. Lassen Sie uns wissen, ob es in Ordnung ist.
@oliviertassinari hat es getan.
Ich habe immer noch ein Problem mit der forwardRef-Lösung oder der Komponente 1, bei der die Textfarbe der Schaltfläche die Farbe der Themenpalette nicht berücksichtigt. Die Textfarbe sollte weiß sein, um mit palette.type: 'dark'
, ist jedoch weiß.
Wahrscheinlich im Zusammenhang mit einer Änderung der MUI, da ich ohne die component
Requisiten immer noch das Problem habe.
Für diejenigen, die hier nachlesen, können Sie zusätzliche Requisiten an ListItemText übergeben ...
<ListItemText
primaryTypographyProps={{
color: 'textPrimary'
}}
primary="Dashboard"
/>
Übrigens, Ihr Beispiel ist jetzt in TS.
Hier ist die Lösung, die mein Problem gelöst hat
<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>
Verwenden Sie daher einfach ListItem als
key = {index}
** {... {to: menu.link}} **
component = {Link}
button = {true}
>
button={true}
macht das UI-Verhalten von Schubladen einfach so wie kein Link.
Für andere, die dies in Typescript versuchen:
Ein einfaches Beispiel für die Verwendung der ListItem-Komponenteneigenschaft zur Angabe von a
import { NavLink } from "react-router-dom";
<List>
<ListItem button={true} {...{ component: NavLink, to: "/Somewhere" }}>
<ListItemIcon>
<ShoppingCartIcon />
</ListItemIcon>
<ListItemText primary="Orders" />
</ListItem>
</List>
oder alternativ, wenn Sie nur eine onClick-Funktion für das ListItem verwenden möchten, zum Beispiel:
<List>
<ListItem button={true} {...{ onClick: () => alert("foo") }}>
<ListItemIcon>
<DashboardIcon />
</ListItemIcon>
<ListItemText primary="Dashboard" />
</ListItem>
</List>
`` `
Das hat bei mir funktioniert
const NavLinkMui = React.forwardRef((props, ref) => (
<NavLink {...props} activeClassName="Mui-selected" ref={ref} />
))
<ListItem button component={NavLinkMui} to={to}>{text}</ListItem>
Die am häufigsten gewählte Antwort schlug nach der Migration von MUI v4 (ich bin auf 4.3.1) aufgrund von "Funktionskomponenten können keine Refs zugewiesen werden. Versuche, auf diese Ref zuzugreifen, schlagen fehl. Wollten Sie React.forwardRef () verwenden?"
Ich habe die
NavLink
-Komponente durch einen Wrapper wie folgt ersetzt: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
Verwendung:
<ListItem button component={NavLinkMui} to='/' > <ListItemIcon> <SlideshowIcon /> </ListItemIcon> </ListItem>
Danke @HugoGresse Das funktioniert einwandfrei :-)
Hilfreichster Kommentar
Dies wird in der Dokumentation behandelt: https://material-ui.com/components/buttons/#third -party-routing-library.