I was creating some header for my app, so I tried to place the hooks in some other file for better organization.
But I'm a bit confused, how do I call this function useHeaderNavStatus() when I click the button in the header tag, without creating another useEffect and useState in Header component? Is it possible or I'm too blind?
I appreciate any help! :D
Here is the file structure:
Header Component
const Header = () => {
const headerNav = useHeaderNavStatus();
return (
<header>
<button
ref={headerNav.toggleRef}
onClick={What do I do here?}>
Menu
</button>
</header>
);
}
Hooks file
import { useEffect, useRef, useState } from 'react';
const useHeaderNavStatus = () => {
// Creating ref for toggle button
const toggleRef = useRef<HTMLButtonElement>(null);
// Creating state to know if nav is showing or not
const [isActive, setIsActive] = useState(false);
// This function opens and closes nav
const updateBodyScroll = () => {
setIsActive(!isActive);
const body = document.body.classList;
if (isActive) {
body.remove('no-scroll');
} else {
body.add('no-scroll');
}
};
// This function closes the nav on outside click
const closeNavOnOutsideClick = (event: MouseEvent) => {
if (!toggleRef.current?.contains(event.target as Node))
updateBodyScroll();
};
// Adds and removes event listener to know the target click
useEffect(() => {
if (isActive) {
window.addEventListener('mousedown', closeNavOnOutsideClick);
return () =>
window.removeEventListener('mousedown', closeNavOnOutsideClick);
}
});
return { toggleRef, isActive };
};
CodePudding user response:
Your hook should also return a function that opens the nav:
const openNav = () => setIsActive(true);
return { toggleRef, isActive, openNav };
And then use it:
const Header = () => {
const headerNav = useHeaderNavStatus();
return (
<header>
<button
ref={headerNav.toggleRef}
onClick={headerNav.openNav}>
Menu
</button>
</header>
);
}