10

I am trying to create a simple Hamburger Menu component using React & Typescript. What I want to do is to pass the onClick event handler to this menu componunent as a prop. This is the code that I currently have:

function Hamburger({ onClick }) {
  return (
    <Box
      as="button"
      type="button"
      p="1"
      fontSize="2xl"
      color="gray.600"
      onClick={onClick}
      display={{ base: "block", lg: "none" }}
    >
      <HiOutlineMenu />
    </Box>
  )
}

However, typescript complains about the {onClick} prop that is being passed:

Binding element 'onClick' implicitly has an 'any' type

I thought that I could fix this by hovering over the onClick key in the Box component and seeing what type onClick takes. Hovering over that key produces the following message:

enter image description here

As such, I thought to modify the {onClick} prop as follows:

function Hamburger({ onClick }: React.MouseEventHandler | undefined) {

But that just produces a new error on {onClick}:

Property 'onClick' does not exist on type 'MouseEventHandler<Element> | undefined'.ts(2339)
var onClick: any

I am now at a loss of what to do. As such, I am wondering -- how should I type {onClick}?

Thanks.

2
  • 1
    function Hamburger({ onClick }: { onClick?: React.MouseEventHandler }) should work Commented Jun 24, 2021 at 13:49
  • 1
    Thanks -- that did it. If you want, you can add that as an answer and I'll mark it as the accepted answer. Commented Jun 24, 2021 at 14:01

3 Answers 3

19

Correct typing for your Hamburger functional component is:

function Hamburger({ onClick }: { onClick? : React.MouseEventHandler }): JSX.Element {
    // actual code
}

As number of props grow, inline type declarations may get messy. So, it's a good habit to move them into designated type:


type Props = {
    onClick?: React.MouseEventHandler
}

function Hamburger({ onClick }: Props) JSX.Element {
    // actual code
}

It also has benefits if later you'll have to accept children prop in this component. Then you may use React.FC helper with Props type:

const Hamburger: React.FC<Props> = ({ onClick, children }) => { // no need to type `children` prop yourself
    // actual code
}
Sign up to request clarification or add additional context in comments.

Comments

3
import { forwardRef } from "react";
import { Box } from "@chakra-ui/react";
import { HiOutlineMenu } from "react-icons/hi";

type THamburgerProps = React.ComponentPropsWithoutRef<"button">;

const Hamburger = forwardRef<HTMLButtonElement, THamburgerProps>(
  ({ ...props }, ref) => {
    return (
      <Box
        as="button"
        ref={ref}
        type="button"
        p="1"
        fontSize="2xl"
        color="gray.600"
        display={{ base: "block", lg: "none" }}
        {...props}
      >
        <HiOutlineMenu />
      </Box>
    );
  }
);

Hamburger.displayName = "Hamburger";

function App() {
  return <Hamburger onClick={() => console.log("hamburger clicked!")} />;
}

Comments

2

It is better to use types provided by react. Consider this:

import React, { FunctionComponent, MouseEventHandler } from 'react';

interface Props {
  onClick?: MouseEventHandler;
}

const Button: FunctionComponent<Props> = ({ onClick }) => (
    <Box
      as="button"
      type="button"
      p="1"
      fontSize="2xl"
      color="gray.600"
      onClick={onClick}
      display={{ base: "block", lg: "none" }}
    >
      <HiOutlineMenu />
    </Box>
);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.