New to react & typescript so if there's a better way to do this, please let me know. I want to combine these 2 functions in a React component to be 1:
// Opens the overlay menu
function openOverlayHandler() {
setOverlayIsOpen(true);
}
// Closes the overlay menu
function closeOverlayHandler() {
setOverlayIsOpen(false);
}
Instead something like this:
function toggleOverlayHandler(isOpen: boolean): void {
setOverlayIsOpen(isOpen)
}
It would be fired using the onClick attribute. Examples:
<Image
src={iconMenu}
alt="Open Menu"
className={styles["header__overlay-icon"]}
onClick={toggleOverlayHandler(true)}
/>
In case it helps, here's the complete component:
// Import React modules
import { useState } from "react";
// Import Next modules
import Image from "next/image";
import Link from "next/link";
// Import Next Drupal modules
import { getMenu } from "next-drupal";
// Import component dependencies
import OverlayMenu from "../../molecules/OverlayMenu";
// Import media
import logo from "../../../public/svgs/logo.svg";
import iconMenu from "../../../public/svgs/icon-menu.svg";
import iconEmail from "../../../public/svgs/icon-email.svg";
import iconPhone from "../../../public/svgs/icon-phone.svg";
// Import component module styles
import styles from "./header.module.scss";
// Create the component
const Header: React.FC<{ menu: any }> = ({ menu }) => {
// Define the component states
const [overlayIsOpen, setOverlayIsOpen] = useState(false);
// @TODO - Can we collapse the 2 functions below to one, something like toggleOverlayHandler(isOpen: boolean)
// Opens the overlay menu
function openOverlayHandler() {
setOverlayIsOpen(true);
}
// Closes the overlay menu
function closeOverlayHandler() {
setOverlayIsOpen(false);
}
return (
<header className={styles.header}>
<Link href="/">
<a className={styles["header__logo-link"]}>
<Image
src={logo}
alt={process.env.SITE_NAME}
className={styles.header__logo}
/>
</a>
</Link>
<ul className={styles["header__contact-list"]}>
<li>
<a href={`tel:${process.env.PRIMARY_PHONE}`}>
<Image src={iconPhone} alt="Call Us" />
</a>
</li>
<li>
<a href={`mailto:${process.env.PRIMARY_EMAIL}`}>
<Image src={iconEmail} alt="Email Us" />
</a>
</li>
</ul>
<nav>
<ul>
{menu?.map((item: any) => {
return (
<li key={item.id}>
<Link href={item.url} passHref>
<a>{item.title}</a>
</Link>
</li>
);
})}
</ul>
</nav>
<Image
src={iconMenu}
alt="Open Menu"
className={styles["header__overlay-icon"]}
onClick={openOverlayHandler}
/>
{overlayIsOpen && <OverlayMenu onCloseClick={closeOverlayHandler} />}
</header>
);
};
// Define the props at build
export async function getStaticProps() {
const { tree } = await getMenu("main");
return {
props: {
menu: tree,
},
};
}
// Export the component
export default Header;
CodePudding user response:
Instead something like this:
function toggleOverlayHandler(isOpen: boolean): void { setOverlayIsOpen(isOpen) }
The above code is fine, but you're using it wrong. When you do this:
onClick={toggleOverlayHandler(true)}
...that means "immediately call toggleOverlayHandler(true)
, and pass its return value into onClick
". So you end up running the code during rendering, not when the click happens. Instead, you need to pass a function to onClick, as in:
onClick={() => toggleOverlayHandler(true)}