function Navbar() {
const [shownavcontents, setShownavcontents] = useState(false)
if(shownavcontents){
document.getElementsByClassName("navbardivofmobiledevice").style.display = "none";
}else{
document.getElementsByClassName("navbardivofmobiledevice").style.display = "block";
}
return (
<>
<div className="top">
<Searchbar />
<AiOutlineMenu size={20} className="outlinemenu" onClick={() => {setShownavcontents(true)}} />
</div>
<div className="navbardivofmobiledevice">
<ul>
<li>
<a href="#home">Home</a>
</li>
<li>
<a href="#memebers">Members</a>
</li>
<li>
<a href="#allposts">All Posts</a>
</li>
<li>
<a href="#myposts">My Posts</a>
</li>
</ul>
</div>
</>
);
}
As you see I am trying to make responsive navbar, in this case, for mobile devices. I've faced one problem. I've made button on top of navbar and some navbar contents which I want to display only whenever user will click this button and vice versa. So I tried using hooks to check if the user clicked the button which works perfectly, only thing that doesn't works is this if else statements it seems like document.getElementsByClassName("navbardivofmobiledevice").style.display = "none";
doesn't have an effect here. So my question is what is the alternative of this? What can I do here?
CodePudding user response:
This is imperative code:
document.getElementsByClassName("navbardivofmobiledevice").style.display = "none";
With React, you rarely get references to DOM elements and update them manually, and in any case, you do it using Refs
, not with the getElement...
or querySelector...
methods). Instead, you write declarative code and let React take care of the DOM updates for you.
In this case, simply add or remove a hidden
attribute or CSS class that has display: none
from your JSX:
function Navbar() {
const [shownavcontents, setShownavcontents] = useState(false);
return (
<>
<div className="top">
<Searchbar />
<AiOutlineMenu size={20} className="outlinemenu" onClick={() => {setShownavcontents(true)}} />
</div>
<div className="navbardivofmobiledevice" hidden={ !shownavcontents }>
<ul>
<li>
<a href="#home">Home</a>
</li>
<li>
<a href="#memebers">Members</a>
</li>
<li>
<a href="#allposts">All Posts</a>
</li>
<li>
<a href="#myposts">My Posts</a>
</li>
</ul>
</div>
</>
);
}
If you prefer to use a class, assuming you have defined a CSS class .isHidden { display: none; }
you would use this line instead:
<div className={ `navbardivofmobiledevice${ shownavcontents ? '' : ' isHidden' }` }>
Regarding what some comments are mentioning about rendering that conditionally like so:
function Navbar() {
const [shownavcontents, setShownavcontents] = useState(false);
return (
<>
<div className="top">
<Searchbar />
<AiOutlineMenu size={20} className="outlinemenu" onClick={() => {setShownavcontents(true)}} />
</div>
{ shownavcontents && (
<div className="navbardivofmobiledevice">
<ul>
<li>
<a href="#home">Home</a>
</li>
<li>
<a href="#memebers">Members</a>
</li>
<li>
<a href="#allposts">All Posts</a>
</li>
<li>
<a href="#myposts">My Posts</a>
</li>
</ul>
</div>
) }
</>
);
}
I would avoid that, as hiding your main navigation from Google and other search engines will harm your SEO. You need to hide it visually but still have it in the DOM.
If you want to do better than that, add all the appropriate ARIA attributes and logic for a navigation menu with nested submenus, as explained here:
https://www.w3.org/WAI/ARIA/apg/example-index/menubar/menubar-navigation