Skip to content

Instantly share code, notes, and snippets.

@chaance
Created September 12, 2018 14:24
Show Gist options
  • Save chaance/6262322d5949cf5700ae4d071fe8f700 to your computer and use it in GitHub Desktop.
Save chaance/6262322d5949cf5700ae4d071fe8f700 to your computer and use it in GitHub Desktop.
Recursive menu component (React + Next.js)
import React, { Component } from 'react';
import Link from 'next/link';
import { uniqueId } from 'lodash';
import PropTypes from 'prop-types';
class Menu extends Component {
renderSubMenu = (children) => {
if (children && children.length > 0) {
return (
<ul className="menu__submenu">{this.renderMenuItems(children)}</ul>
);
}
};
renderMenuItems = (items) =>
items.map((item, i) => {
const { href, target, label, children } = item;
return (
<li className="menu__item" key={uniqueId(`item-${i}-`)}>
<Link href={href} key={uniqueId(`link-${i}-`)}>
<a className="menu__link" target={target}>
{label}
</a>
</Link>
{this.renderSubMenu(children)}
</li>
);
});
render() {
const className = this.props.className
? `menu ${this.props.className}`
: 'menu';
return (
<ul className={className}>{this.renderMenuItems(this.props.items)}</ul>
);
}
}
const menuItemShape = PropTypes.shape({
href: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
target: PropTypes.string
});
menuItemShape.children = PropTypes.arrayOf(menuItemShape);
Menu.propTypes = {
className: PropTypes.string,
items: PropTypes.arrayOf(menuItemShape).isRequired
};
export default Menu;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment