I am using React hooks, I have 2 components:
- Curtain
- Navbar
Here is my code for the Curtain
component:
function Curtain(){
return(
<div className="curtain__div">
<ul className="menu__items">
<li className="about">abc</li>
<li>def</li>
<li>ghi</li>
<li>klm</li>
</ul>
</div>
);
}
export default Curtain;
Here is my code for the NavBar
component:
function NavBar(){
const [show, setShow] = useState(false);
return(
<nav className="nav__bar">
<ul className="menu">
<li className="menu__icon" onClick={() => setShow(true)}><box-icon name='menu' color="floralwhite" size="md"/>
<Curtain/>
</li>
</ul>
</nav>
);
}
export default NavBar;
My Question:
I want to show the Curtain
component, when the user click on the li which is of className="menu__icon"
, and to be hidden when the user clicks on it again.
I am using React hooks, I have 2 components:
- Curtain
- Navbar
Here is my code for the Curtain
component:
function Curtain(){
return(
<div className="curtain__div">
<ul className="menu__items">
<li className="about">abc</li>
<li>def</li>
<li>ghi</li>
<li>klm</li>
</ul>
</div>
);
}
export default Curtain;
Here is my code for the NavBar
component:
function NavBar(){
const [show, setShow] = useState(false);
return(
<nav className="nav__bar">
<ul className="menu">
<li className="menu__icon" onClick={() => setShow(true)}><box-icon name='menu' color="floralwhite" size="md"/>
<Curtain/>
</li>
</ul>
</nav>
);
}
export default NavBar;
My Question:
I want to show the Curtain
component, when the user click on the li which is of className="menu__icon"
, and to be hidden when the user clicks on it again.
4 Answers
Reset to default 8The simplest option is just to return the component conditionally based on your state:
return(
<nav className="nav__bar">
<ul className="menu">
<li className="menu__icon" onClick={() => setShow(currentShow => !currentShow)}>
<box-icon name='menu' color="floralwhite" size="md"/>
{ show ? <Curtain/> : null }
</li>
</ul>
</nav>
);
To toggle the show
off again, you can change
onClick={() => setShow(true)}
to instead invert the current state like this:
onClick={() => setShow(!show)}
// or
onClick={() => setShow(currentShow => !currentShow)}
(The second option is technically better as it avoids race conditions if you were to repeatedly click the button very quickly)
First, currently you're only ever setting the state to "show" the component, never to "hide" it:
onClick={() => setShow(true)}
Instead of always setting the state to true
, toggle the state from whatever its current value is:
onClick={() => setShow(!show)}
Second, you would use that state value to conditionally render the element. So instead of always rendering it:
<Curtain/>
You would conditionally render it based on state:
{ show ? <Curtain/> : null }
You need to pass the state of show as a prop to curtain.
Then you can conditionally show/hide using classname or something.
Also, in setShow, pass the value where it could be true or false by prefixing with a !. There you are passing true or false.
function NavBar(){
const [show, setShow] = useState(false);
return(
<nav className="nav__bar">
<ul className="menu">
<li className="menu__icon" onClick={() => setShow(!show)}><box-icon name='menu' color="floralwhite" size="md"/>
<Curtain show={show}/>
</li>
</ul>
</nav>
);
Then in the curtain component, you can do something like this:
function Curtain(props){
return(
<div className="curtain__div">
<ul className="menu__items">
<li className={props.show ? 'show-class' : 'hide-class'}>abc</li>
<li>def</li>
<li>ghi</li>
<li>klm</li>
</ul>
</div>
);
You just need to change your handle function to toggle, rather than always setting true - this should do the trick
function NavBar(){
const [show, setShow] = useState(false);
return(
<nav className="nav__bar">
<ul className="menu">
<li className="menu__icon" onClick={() => setShow(!show)}><box-icon name='menu' color="floralwhite" size="md"/>
<Curtain/>
</li>
</ul>
</nav>
);
}
export default NavBar;