简体   繁体   中英

In React.js w/Typescript, how do you create a onClick function that also passes another parameter?

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;

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)}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM