I am designing a responsive mega navigation bar using reactjs. It’s working for desktop device but on mobile view, I could not able to show or hide sub menu when its associated parent menu is clicked. This is what I am trying to do
JavaScript
x
153
153
1
const menus = [
2
{ id: 1, name: "Home", link: "/" },
3
{
4
id: 3,
5
name: "New",
6
children: [{ id: 1, name: "New Arrival", link: "/new" }]
7
},
8
{
9
id: 2,
10
name: "Shop",
11
children: [
12
{
13
id: 1,
14
name: "Men's Fashion",
15
children: [
16
{
17
id: 1,
18
name: "Polo",
19
link: "/polo"
20
},
21
{ id: 2, name: "Tees", link: "/tees" }
22
]
23
},
24
{
25
id: 2,
26
name: "Women Fashion",
27
children: [
28
{
29
id: 1,
30
name: "Shorts",
31
link: "/shorts"
32
},
33
{
34
id: 2,
35
name: "Tees",
36
link: "/women/tees"
37
}
38
]
39
}
40
]
41
}
42
];
43
44
const MegaMenu = () => {
45
const [active, setActive] = React.useState(false);
46
const [toggle, setToggle] = React.useState(false);
47
const [activeMenuName, setActiveMenuName] = React.useState("");
48
const handleMainMenuClick = () => {
49
setActive(!active);
50
};
51
const toggleDrawer = () => {
52
setToggle(!toggle);
53
};
54
const hideSubMenu = () => {
55
setActive(!active);
56
};
57
const handleMenuName = (menuName) => {
58
setActiveMenuName(menuName);
59
};
60
return (
61
<>
62
<header className="header">
63
<div className="container">
64
<div className="row v-center">
65
<div className="header-item item-left">
66
<div className="logo">
67
<a href="#">Brand</a>
68
</div>
69
</div>
70
{/* menu start here */}
71
<div className="header-item item-center">
72
<div
73
className={`menu-overlay ${toggle ? "active" : ""}`}
74
onClick={toggleDrawer}
75
></div>
76
<nav className={`menu ${toggle ? "active" : ""}`}>
77
<div className={`mobile-menu-head ${toggle ? "active" : ""}`}>
78
<div className="go-back" onClick={hideSubMenu}>
79
Back
80
</div>
81
<div className="current-menu-title">{activeMenuName}</div>
82
<div className="mobile-menu-close" onClick={toggleDrawer}>
83
×
84
</div>
85
</div>
86
<ul className="menu-main" onClick={handleMainMenuClick}>
87
{menus.map((menu) => {
88
return (
89
<li
90
key={menu.id}
91
className={
92
menu.children ? "menu-item-has-children" : ""
93
}
94
onClick={() => handleMenuName(menu.name)}
95
>
96
{menu.link ? (
97
<a href={menu.link}>
98
{menu.name} <i class="fa fa-angle-down"></i>
99
</a>
100
) : (
101
<a href="#">{menu.name}</a>
102
)}
103
{menu.children && (
104
<div
105
className={`sub-menu mega-menu mega-menu-column-4 ${
106
active ? "active" : ""
107
}`}
108
>
109
{menu.children.map((child) => {
110
return (
111
<div
112
className="list-item text-center"
113
key={child.id}
114
>
115
<a href="#">
116
<img src="img/p1.jpg" alt="new Product" />
117
<h4 className="title">{child.name}</h4>
118
</a>
119
</div>
120
);
121
})}
122
</div>
123
)}
124
</li>
125
);
126
})}
127
</ul>
128
</nav>
129
</div>
130
<div className="header-item item-right">
131
<a href="#">
132
<i className="fas fa-search"></i>
133
</a>
134
<a href="#">
135
<i className="far fa-heart"></i>
136
</a>
137
<a href="#">
138
<i className="fas fa-shopping-cart"></i>
139
</a>
140
{/* mobile menu trigger */}
141
<div className="mobile-menu-trigger" onClick={toggleDrawer}>
142
<span></span>
143
</div>
144
</div>
145
</div>
146
</div>
147
</header>
148
</>
149
);
150
};
151
152
export default MegaMenu;
153
I have a code on sandbox as well and here it is
https://codesandbox.io/s/weathered-resonance-9n2hr?file=/src/mega-menu/index.js:50-4734
Advertisement
Answer
You should set active
only to the activeMenuName
that is clicked. Also when click go back
you should reset activeMenuName
to the default state. Also, I check if toggle
is enabled so only onClick
events are enabled and vice versa.
Check my code it’s tested.
JavaScript
1
107
107
1
const MegaMenu = () => {
2
const [active, setActive] = React.useState(false);
3
const [toggle, setToggle] = React.useState(false);
4
const [activeMenuName, setActiveMenuName] = React.useState("");
5
const handleMainMenuClick = () => {
6
setActive(!active);
7
};
8
const toggleDrawer = () => {
9
setActiveMenuName("");
10
setToggle(!toggle);
11
};
12
const hideSubMenu = () => {
13
setActiveMenuName("");
14
};
15
const handleMenuName = (menuName) => {
16
setActiveMenuName(menuName);
17
};
18
19
const renderLiComp = (menu) =>{
20
if(toggle){
21
return <li
22
key={menu.id}
23
className={ menu.children ? "menu-item-has-children" : "" }
24
onClick={() =>handleMenuName(menu.name)}
25
>
26
{menu.link
27
? (<a href={menu.link}>{menu.name} <i className="fa fa-angle-down"></i></a>)
28
: (<a href="#">{menu.name}</a>)}
29
{activeMenuName && getSelectedChildren()}
30
</li>;
31
}else{
32
return <li
33
key={menu.id}
34
className={ menu.children ? "menu-item-has-children" : "" }
35
onMouseEnter={()=>handleMenuName(menu.name)}
36
>
37
{menu.link
38
? (<a href={menu.link}>{menu.name} <i className="fa fa-angle-down"></i></a>)
39
: (<a href="#">{menu.name}</a>)}
40
{activeMenuName && getSelectedChildren()}
41
</li>;
42
}
43
44
}
45
46
const renderListElements = () =>{
47
48
return menus.map(renderLiComp);
49
}
50
51
const renderChildren = (childs) =>{
52
const children = childs.map(x =>
53
<div className="list-item text-center" key={x.id}>
54
<a href="#"><img src="img/p1.jpg" alt="new Product" />
55
<h4 className="title">{x.name}</h4>
56
</a>
57
</div>
58
);
59
return children;
60
}
61
62
const getSelectedChildren = () =>{
63
return menus.map(x => {
64
let selected;
65
if(x.name === activeMenuName){
66
if(x.children){
67
selected = <div key={x.id} className='sub-menu mega-menu mega-menu-column-4 active'>{renderChildren(x.children)}</div>;
68
}else{
69
selected = <div key={x.id} className='sub-menu mega-menu mega-menu-column-4 active'></div>;
70
}
71
}
72
return selected;
73
});
74
}
75
76
return (
77
<>
78
<header className="header">
79
<div className="container">
80
<div className="row v-center">
81
<div className="header-item item-left">
82
<div className="logo">
83
<a href="#">Brand</a>
84
</div>
85
</div>
86
{/* menu start here */}
87
<div className="header-item item-center">
88
<div
89
className={`menu-overlay ${toggle ? "active" : ""}`}
90
onClick={toggleDrawer}
91
></div>
92
<nav className={`menu ${toggle ? "active" : ""}`}>
93
<div className={`mobile-menu-head ${toggle ? "active" : ""}`}>
94
<div className="go-back" onClick={hideSubMenu}>
95
Back
96
</div>
97
<div className="current-menu-title">{activeMenuName}</div>
98
<div className="mobile-menu-close" onClick={toggleDrawer}>
99
×
100
</div>
101
</div>
102
<ul className="menu-main" onClick={handleMainMenuClick}>
103
{renderListElements()}
104
</ul>
105
</nav>
106
</div>
107
The sandbox Link https://codesandbox.io/s/nifty-cloud-kuryf?file=/src/mega-menu/index.js