The reason I created this is because the Material UI way of doing a simple 'menu that opens below the button' is convoluted as hell (see the 'toggle menu grow' example, and check the code out. I've basically copied the code for that, and put it in one nice wrapper.
Here's the usage of the component:
<NavDropdownMenu
buttonProps={{
variant: "contained",
color: "secondary"
}}
buttonChildren={"foo bar"}
>
<MenuItem onClick={this.handleA}>Profile</MenuItem>
<MenuItem onClick={this.handleB}>My account</MenuItem>
<MenuItem>Logout</MenuItem>
</NavDropdownMenu>
Notes:
- We can pass through whatever material props to the button.
- We can put whatever content we like inside the button. (e.g. icons, avatars).
- We put whatever we like as menu items, and bind our own onclick events to them.
Under the hood, in order to both trigger the close menu functionality, as well as allow the user to bind their own click events to the menu items, I have this code that uses React.cloneElement
:
<MenuList>
{children.map((child, i) => {
return React.cloneElement(child, {
...child.props,
...{
onClick: this.generateOnClick(child.props.onClick),
key: `${menuId}${i}`
}
});
})}
</MenuList>
And that function:
generateOnClick = fn => {
if (fn)
return () => {
fn();
this.handleMenuClose();
};
else {
return this.handleMenuClose;
}
};
Now, I haven't put in PropTypes; I have to confess I'm not in the habit of using them. And there's probably some more extensibility I could add - (e.g. configuring the placement of the menu).
But other than that, are there glaring issue with this code that make it a bad idea?