how to set MenuItem be <a> inside <li> - reactjs

I'm new to Material-UI.
I want to make some popover and saw Menu and MenuItem in Menu Demo. They are perfect except for one thing. I want the menu item to be link.
By default MenuItem is li, (I think) because Menu is ul. But it is not so hard that make an item link by setting component="a" or component={RouterLink}. But in this case, they lose li.
For Screen Reader like program, I heard that using an appropriate Html tag is important. (It is called Semantic Web. Right?)
In this perspective, I want to menu items to be a inside li.
-- Trial --
<MenuItem>
<a>link text</a>
</MenuItem>
a is inside li. But it looks different from the case below.
<MenuItem component="a" href="/">
link text
</MenuItem>
Then, I try
<MenuItem>
<a style={{all: "inherit"}}>
link text
</a>
</MenuItem>
It looks satisfactory, but the color changes after clicking it, (I think) because a:visited { color: ...; } is not inherited.
Finally I tried
<li>
<MenuItem component="a" href"/">
link text
</MenuItem>
</li>
Yeah. It solves all problems. But, what if I forget to add li?
My menu contains many items. Some of them are link and others are not. Then should I add li directly by distinguishing only the cases of link?
-- Question --
Is my solution is best? How about you? Please share your way.

Semantically, MenuItem is more suitable for li because it represents an item in a list. The component props's default value of MenuItem is 'li' after all. So I'd go for:
<MenuItem>
<a style={{all: "inherit"}}>
link text
</a>
</MenuItem>
But, what if I forget to add li?
That's one reason to use React, you can easily de-duplicate part of your components by creating another component and reuse it:
const useStyles = makeStyles((theme) => ({
root: {
"& a:visited": {
color: theme.palette.primary.main
}
}
}));
function MenuItemLink({ children, href, onClick }) {
const classes = useStyles();
return (
<MenuItem onClick={onClick} className={classes.root}>
<a href={href}>{children}</a>
</MenuItem>
);
}
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItemLink href="/" onClick={handleClose}>
Profile
</MenuItemLink>
<MenuItemLink href="/" onClick={handleClose}>
My account
</MenuItemLink>
<MenuItemLink href="/" onClick={handleClose}>
Logout
</MenuItemLink>
</Menu>
Live Demo

Related

Render the Material UI Menu as <nav> and its children as <a>?

I've a Material UI Menu, redered as <div> > <ul> <li> by default. I wanto to turn it into a <div> <nav> <a>.
I'm able to change MenuItem and turn into a <a>. But I can't find a way to turn the <ul> into a <nav>, there is no component prop. Material UI is so customizable that I'm sure I'm missing something and it's my mistake.
<Menu open={true}>
<MenuItem component='a'>Profile</MenuItem>
<MenuItem component='a'>Settings</MenuItem>
<MenuItem component='a'>Logout</MenuItem>
</Menu>
I can also use the MenuList API as child of Menu, but it only render another level below the <ul>.
MenuList inherits the props from the List component which you can use to change the ul to a nav
<Menu
open={true}
MenuListProps={{
"aria-labelledby": "basic-button",
component: "nav"
}}
>

How to get a specific ListItem from Menu Component in MUI for React

I have a List that has several ListItems which I get from an array, let's call it myCollection. Each ListItem has a MenuIcon which opens a Menu, showing an option to delete the item. The simplified code looks like this:
<List>
<Menu
open={Boolean(anchorEl)}
anchorEl={anchorEl}
...>
<MenuItem onClick={() => handleDelete(⚡collectionItem)}>Delete</MenuItem>
</Menu>
{myCollection.map((collectionItem) => (
<ListItem secondaryAction={
<IconButton onClick={(e) => setAnchorEl(e.currentTarget)}>
<MoreVertIcon />
</IconButton>
}>
{collectionItem.name}
</ListItem>
)}
</List>
My problem is that I need to know which item in myCollection was selected to pass it to the delete function. However, I don't have a reference to the current collectionItem in the myCollection array from the Menu. Moving the Menu into the map function makes no sense because multiple menus would be rendered. How can I solve this problem?
I solved it by giving the IconButtons custom HTML data attributes, e.g.
<IconButton data-collection-id={collection.id} onClick={...}>
...
</IconButton>
Then, in the onClick function, we can retrieve it by using event.currentTarget.getAttribute("data-collection-id").

How to use Next.js Link (next/link) component in a Material UI Menu?

I have a Material ui menu in the following way:
<Menu id="simple-menu" anchorEl={anchorEl} keepMounted open={!!anchorEl} onClose={handleClose}>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>Log Out</MenuItem>
</Menu>
and want to use next.js Link tags with theMenuItem. What is the best way to do this?
I tried the following things:
The following doesn't render the <a> tag, but adds href to the <li> tag.
<Link href={'#'} passHref><MenuItem onClick={handleClose}>Log Out</MenuItem></Link>
I could add a prop to MenuItem to render <a> instead of <li> tag, however, since the menu is nested under <ul> tag, I'm not sure if having <ul><a>Log Out</a></ul> is a good idea
The following throws an error
<MenuItem onClick={handleClose} component={<Link href={'#'}>Log Out</Link>}></MenuItem>
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
As mentioned in the other answer giving the Link tag within the MenuItem tag will work as required and for the styling issues you have to give a textDecoration: 'none' and color: '#000' within the Link tag to avoid the underline and blue color of the Link text.
<MenuItem>
<Link
style={{
textDecoration: 'none',
color: '#000'
}}
href="#"
>
Log Out
</Link>
</MenuItem>
This is what worked for me that also disables "the regular blue link with underline in the menu":
<MenuItem>
<Link href="#">
<a
style={{
textDecoration: 'none',
color: '#000'
}}
>
Profile
</a>
</Link>
</MenuItem>
You can put "Link" component inside the "MenuItem" component.
<MenuItem><Link href="#">Log Out</Link></MenuItem>
Add a tag inside link
<MenuItem onClick={handleClose} component={<Link href={'#'}><a>Log Out</a></Link>}></MenuItem>
Component prop inside <MenuItem> is The component used for the root node. Either a string to use a HTML element or a component. which defauts to <li> as material-ui official says.
If you want to keep <ul><li></li></ul> structure, you have to nest your <Link> component inside of <MenuItem> component.
So this may be what you wanted.
<MenuItem onClick={handleClose}>
<Link href={'#'}>Log Out</Link>
</MenuItem>
See if the below code fix this, Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object:
const ALink = ({ url, linkText }) => <Link href={url}>
<a>{ linkText }</a>
</Link>
<MenuItem onClick={handleClose} component={ ALink({url: '#', linkText: 'Log Out') }></MenuItem>
I think the other answers actually have it backward, which disrupts the normal layout of the MenuItem. (For me, the menu items became taller and the text was too low.) This worked much better, and doesn't require trying to restyle the <a> tag yourself:
<NextLink href="#" passHref>
<MenuItem component="a">
Log Out
</MenuItem>
</NextLink>

how to menu item redirect to a link using href?

I'm using MenuItem from material-ui, and I want to open a link in a new tab when the menu item is clicked. I'm using simple:
<MenuItem href="www.google.com" onClick={handleClose}> Google </MenuItem>
But nothing happens. Anyone know why?
Material-ui's MenuItem does not have an href prop, so it will pass that down to the root element (li tag by default).
If you want to use an href you would need to use an a tag as the component, which would then pass down the href to it instead of an li. To open it in a new tab you need to also give it a prop target="_blank".
Result:
<MenuItem
href="www.google.com"
target="_blank"
component="a"
onClick={handleClose}
> Google </MenuItem>
You can write in the onClick={window.location.href = "www.google.com"}

Unable to show Menu item by clicking on the icon using Reactjs

I'm new to framework, I wanted to show menu item when we click on the icon, I couldn't able to figure it out where I'm going wrong.
here is the code:
<div>
<IconButton
aria-label="more"
aria-controls="simple-menu"
aria-haspopup="true"
onClick={this.handleClick}
>
<AccountBalanceIcon />
</IconButton>
<Menu
id="simple-menu"
anchorEl={this.state.anchorEl}
keepMounted
open={Boolean(this.state.anchorEl)}
onClose={this.handleClose}
>
<MenuItem onClick={this.handleClose}>Profile</MenuItem>
<MenuItem onClick={this.handleClose}>My account</MenuItem>
<MenuItem onClick={this.handleClose}>Logout</MenuItem>
</Menu>
</div>
Can anyone help me in getting a popup while I click on the icon
The IconButton does not have a value, so you're setting state to undefined. You just want the target anyway, since its the element itself that will serve as the anchor, not the value.
Change your handler to this:
handleClick = event => {
this.setState({ anchorEl: event.target });
};
Also: Please provide all the relevant code the the question itself. The event handlers are the most important part of the problem and they are only located off-site.

Resources