I trying to find a way to open the navbar of ReactJS app when i'm clicking on my "MENU
" button.
At the beginning my nav ponent have a width
of 0px
(with overflow : hidden
). When i'm clicking on the button my nav should have a width
of 400px
. I'm a beginner with React.
I have two React Components :
Topbar
export default function Topbar() {
return (
<div className="topbar__container">
<div className='topbar__menuButton'>
<Link className="topbar__link">MENU</Link>
</div>
<div className="topbar__title">
<Link to="/" className="topbar__link">EDGAR</Link>
</div>
</div>
)
}
Nav
const Nav = () => {
return (
<div className="navbar__container">
<Query query={CATEGORIES_QUERY} id={null}>
{({ data: { categories } }) => {
return (
<nav className="nav">
<ul>
{categories.map((category, i) => {
return (
<li key={category.id}>
<Link to={`/category/${category.id}`} className="nav__link">
{category.name}
</Link>
</li>
)
})}
</ul>
</nav>
)
}}
</Query>
</div>
)
}
export default Nav
I trying to find a way to open the navbar of ReactJS app when i'm clicking on my "MENU
" button.
At the beginning my nav ponent have a width
of 0px
(with overflow : hidden
). When i'm clicking on the button my nav should have a width
of 400px
. I'm a beginner with React.
I have two React Components :
Topbar
export default function Topbar() {
return (
<div className="topbar__container">
<div className='topbar__menuButton'>
<Link className="topbar__link">MENU</Link>
</div>
<div className="topbar__title">
<Link to="/" className="topbar__link">EDGAR</Link>
</div>
</div>
)
}
Nav
const Nav = () => {
return (
<div className="navbar__container">
<Query query={CATEGORIES_QUERY} id={null}>
{({ data: { categories } }) => {
return (
<nav className="nav">
<ul>
{categories.map((category, i) => {
return (
<li key={category.id}>
<Link to={`/category/${category.id}`} className="nav__link">
{category.name}
</Link>
</li>
)
})}
</ul>
</nav>
)
}}
</Query>
</div>
)
}
export default Nav
Share
Improve this question
edited Apr 12, 2020 at 17:37
Théo Vogel
asked Apr 12, 2020 at 17:29
Théo VogelThéo Vogel
3481 gold badge3 silver badges16 bronze badges
4
- why did you wrap the Menu in <Link> ? – Asking Commented Apr 12, 2020 at 17:39
- why not use the pre-built and tested bootstrap react library which takes care of a lot of the process that happens under the hood which you are trying to do now. DRY – Saravanan Commented Apr 12, 2020 at 17:40
- @Asking i was trying something else, I just forgot to change this – Théo Vogel Commented Apr 12, 2020 at 17:41
- @Saravanan i wanted to create something more personnal than just using a bootstrap element. I just want to learn something new – Théo Vogel Commented Apr 12, 2020 at 17:43
2 Answers
Reset to default 3To achieve something like that you have to set this logic in the mon parent of both ponent (here App
for the example).
App
will manage a state to determine if the Nav
is open or not. The state is called isMenuOpen
and can be changed using the setIsMenuOpen()
function. We will give to the children Nav
the state isMenuOpen
and to the children TopBar
a callback from the function setIsMenuOpen()
:
App.jsx
import React from "react";
import TopBar from "./TopBar";
import Nav from "./Nav";
export default function App() {
const [isMenuOpen, setIsMenuOpen] = React.useState(false);
return (
<div className="App">
<TopBar setMenuStatus={setIsMenuOpen} />
<Nav isOpen={isMenuOpen} />
</div>
);
}
Then the TopBar
have to set the value of isMenuOpen
to true
using the function setIsMenuOpen()
from the props.
TopBar.jsx
import React from "react";
export default function Topbar({ setMenuStatus }) {
return (
<div className="topbar__container">
<div className="topbar__menuButton">
<button
type="button"
onClick={() => {
setMenuStatus(true);
}}
>
Menu
</button>
</div>
</div>
);
}
Then the ponent Nav
will set a specific class (here .open
) if isOpen
ing from props is true
.
Nav.jsx
import React from "react";
import "./styles.css";
export default function Nav({ isOpen }) {
return (
<div id="nav" className={isOpen ? "open" : ""}>
Menu
</div>
);
}
styles.css
#nav {
display: none;
}
#nav.open {
height: 400px;
display: inline-block;
}
You can try this example in this codesandbox.
import React, {useState} from "react";
import "./styles.css";
export default function App() {
const [toggle, setToggle]= React.useState(false)
const [width, setWidth]= React.useState('')
const showMenu = () => {
setToggle(!toggle)
if(toggle === true) {
setWidth('50px')
}else {
setWidth('500px')
}
}
return (
<div className="App">
<button onClick={showMenu}>Menu</button>
<div style={{width, border:'1px solid red'}}>
<li>text</li>
<li>text</li>
<li>text</li>
<li>text</li>
</div>
</div>
);
}
reproducing link: https://codesandbox.io/s/billowing-flower-rxdk3?file=/src/App.js:0-592