Reputation: 167
Doing my best to hide this sidebar when a user clicks anywhere outside of the focused area. Currently, when I click outside, the sidebar remains open. If I click in an area within the sidebar that isnt a link, the sidebar closes. Just trying to recreate that effect elsewhere in the app. Have no idea to implement this in React/JS
Thank you for any help you can send my way.
import React, { useState } from 'react';
import * as FaIcons from 'react-icons/fa';
import * as AiIcons from 'react-icons/ai';
import { Link } from 'react-router-dom';
import { NavbarData } from './NavbarData';
import '../styles/Navbar.css';
import { IconContext } from 'react-icons';
import onClickOutsideHOC from "react-onclickoutside"; //<-- Should I be using this?
function Navbar() {
const [sidebar, setSidebar] = useState(false);
const showSidebar = () => setSidebar(!sidebar);
const hideSidebar = () => setSidebar(onClickOutsideHOC()); //<-- Should I be using this?
return (
<>
<IconContext.Provider value={{ color: '#fff' }}>
<div className='navbar'>
<Link to='#' className='menu-bars'>
<FaIcons.FaBars onClick={showSidebar} />
</Link>
</div>
<nav className={sidebar ? 'nav-menu active' : 'nav-menu'}>
<ul className='nav-menu-items' onClick={showSidebar}>
<li className='navbar-toggle'>
<Link to='#' className='menu-bars'>
<AiIcons.AiOutlineClose />
</Link>
</li>
{NavbarData.map((item, index) => {
return (
<li key={index} className={item.cName}>
<Link to={item.path}>
{item.icon}
<span>{item.title}</span>
</Link>
</li>
);
})}
</ul>
</nav>
//Commented Out My Attempt Below
{/* <nav>
<nav className={sidebar ? 'nav-menu inactive' : 'nav-menu'}>
<ul className='nav-menu-items' onClick={hideSidebar}>
<li className='navbar-toggle'>
<Link to='#' className='menu-bars'>
<AiIcons.AiOutlineClose />
</Link>
</li>
{NavbarData.map((item, index) => {
return (
<li key={index} className={item.cName}>
<Link to={item.path}>
{item.icon}
<span>{item.title}</span>
</Link>
</li>
);
})}
</ul>
</nav>
</nav>*/}
</IconContext.Provider>
</>
);
}
export default Navbar;
Upvotes: 7
Views: 15291
Reputation: 163
To close a side navigation bar when the user clicks outside of it in a React application, you can add an event listener to the 'document' object that listens for 'mousedown' events. When the user clicks outside the side navigation bar, the event listener will trigger a function that closes the side navigation bar.
Here's some sample code to achieve this:
import React, { useEffect, useRef } from 'react';
function App() {
const sideNavRef = useRef(null);
useEffect(() => {
// Add event listener to the document object
document.addEventListener('mousedown', handleClickOutside);
// Remove event listener when the component unmounts
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, []);
function handleClickOutside(event) {
if (sideNavRef.current && !sideNavRef.current.contains(event.target)) {
// Clicked outside the side navigation bar, close it
// Implement your close side navigation bar logic here
}
}
return (
<div>
<div ref={sideNavRef}>
{/* Your side navigation bar content goes here */}
</div>
<div>
{/* Other content of your application goes here */}
</div>
</div>
);
}
Explanation:
First, we define a sideNavRef using the useRef hook. This reference will be used to check if the click happened inside or outside of the side navigation bar.
We use the useEffect hook to add an event listener to the document object when the component mounts. The useEffect hook's cleanup function is used to remove the event listener when the component unmounts.
The handleClickOutside function checks if the click happened outside of the side navigation bar using the contains method on the sideNavRef reference. If the click happened outside of the side navigation bar, you can implement your close side navigation bar logic in this function.
Finally, we wrap the side navigation bar content inside a div with the ref attribute set to sideNavRef. The other content of your application goes into a separate div.
Upvotes: 4
Reputation: 31
I got a hack, add another empty div with the CSS position absolute before the sidebar and give the sidebar the same position absolute and style as you want. Let the first div have a full view-width and view-hight. The sidebar can have whatever size you want but it will be on higher in z-index then the first div/sibling. Add an onClick function on the first div to close the sidebar because when someone clicks outside of the sidebar, it will be a click on the first div.
Upvotes: 1
Reputation: 357
For this, you can create a custom hook that takes the element you want as a parameter. I created a sandbox for you.
https://codesandbox.io/s/outside-click-hook-uc8bo
We send the ref of the element to the custom hook we created.
const boxRef = useRef(null);
// boxOutsideClick will be true on outside click
const boxOutsideClick = OutsideClick(boxRef);
<div ref={boxRef} className="box">
<h1>Click outside of me</h1>
</div>
And our hook will look like this:
export default function OutsideClick(ref) {
const [isClicked, setIsClicked] = useState();
useEffect(() => {
function handleClickOutside(event) {
if (ref.current && !ref.current.contains(event.target)) {
setIsClicked(true);
} else {
setIsClicked(false);
}
}
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [ref]);
return isClicked;
}
OnMouseDown, we check if the clicked place is in the selected element and update the isClicked value and return.
Upvotes: 7