'React hidden navigation menu
I am working with ReactJS at the moment (I am very much a beginner). What I wanting to do is show/hide a menu component when a link is clicked in the site navigation. The menu is being built as a component that sits within a component (header).
The user clicks the menu button and that then toggles the menu to be shown or hidden, I am however having problems working out where the logic to show and hide the menu component should live the showing an hiding is relatively simple I basically want to add and remove a class to the menu component to show or hide it.
I have a similar show/hide working for my login and register forms, but the show and hide classes for these are added in the header component not the child component, here is my header component JS so far.
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Menu from './menu'; import LoginForm from '../Login'; import RegisterForm from '../Register';
export default class Explore extends Component {
constructor(props) {
super(props);
this.state = {
loginMenuVisible : false,
registerMenuVisible : false,
mainMenuVisible : false
};
console.log(this.state);
//this.triggerMenu = this.triggerMenu.bind(this);
}
render() {
return (
<div className="site__navigation">
<Menu />
<header className="site__header">
<a href="/"><img src="img/logo-full-color.png" alt="meatFree" /></a>
<ul className="header__navigation">
<li className="header__navigation__item">
<a href="/register" onClick={this.toggleMenu.bind(this, 'register')}>Register</a>
<ul className={this.state.registerMenuVisible ? "dropdown visible" : "dropdown"}>
<li>
<LoginForm />
</li>
</ul>
</li>
<li className="header__navigation__item">
<a href="#" onClick={this.toggleMenu.bind(this, 'login')}>Login</a>
<ul className={this.state.loginMenuVisible ? "dropdown visible" : "dropdown"}>
<li>
<LoginForm />
</li>
</ul>
</li>
<li className="header__navigation__item">
<a href="" className="nav__toggle">
Menu
</a>
</li>
</ul>
</header>
</div>
);
}
toggleMenu(type, e) {
e.preventDefault();
console.log(type);
switch(type) {
case 'login':
if(this.state.loginMenuVisible) {
this.setState({loginMenuVisible : false});
} else {
this.setState({
registerMenuVisible : false,
loginMenuVisible : true
});
}
break;
case 'register':
if(this.state.registerMenuVisible) {
this.setState({registerMenu : false});
} else {
this.setState({
registerMenuVisible : true
});
}
break;
case 'menu':
this.setState({mainMenuVisible : true });
}
}
}
AS you see I have a element in the state called mainMenuVisible, I want to be able to maniuplate this within the Menu component.
Solution 1:[1]
I like to keep things simple:
export default class Example extends Component {
constructor(){
super(props)
this.state = {
showMenu: false
}
this.menuShowToggle = this.menuShowToggle.bind(this);
}
menuShowToggle = () => {
this.setState({showMenu: !this.state.showMenu})
}
render = () => {
return (
<div>
<div className={this.state.showMenu ? 'showMenu': 'hideMenu'}>Hidden Menu</div>
<button type="button" onClick={this.menuShowToggle} value="toggle" />
</div>
)
}
}
Solution 2:[2]
To achieve this using your current setup, you could pass the toggleMenu()
function as a prop to your rendered Menu
component
<Menu toggleMenu={this.toggleMenu} />
Then within the Menu
component, you could call toggleMenu()
in a click handler and pass in 'menu' as the type.
Solution 3:[3]
If you are using ReactJs you should consider the following pattern:
1. Set a state specifically to show/hide the the menu
2. Create a function which will toggle the state
3. Add a conditional rendering for the component menu
Here is how the the code can be done:
Step 1.
constructor(props) {
super(props);
this.state = {
isComponenetMenuVisisble : false, // by default to disable it
};
}
Step 2.
toggleComponentMenu = () => {
const isComponenetMenuVisisble = !this.state.isComponenetMenuVisisble;
this.setState({ isComponenetMenuVisisble });
}
Step 3.
{this.state.isComponenetMenuVisisble && <Menu />}
// if isComponenetMenuVisisble is true render <Menu />
And then you can add the event handler like the following
<div className="your-element" onClick={this.toggleComponentMenu}>
... your stuff
</div>
A good point to highlight in the code above is that I am using a method rather than a function in step 2. When using a method instead of a function there will be no need to bind the function on event handlers because this context will be the class itself. Much more details can be found about this in here http://blog.andrewray.me/react-es6-autobinding-and-createclass/
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | wnamen |
Solution 2 | Cent |
Solution 3 |