DEV Community

Cover image for ReactJS Anti Pattern ~Props missing HTML attributes~
Ogasawara Kakeru
Ogasawara Kakeru

Posted on

ReactJS Anti Pattern ~Props missing HTML attributes~

When designing shared components, it is essential to ensure that the native behavior of HTML is not compromised. For example, when using the button element, you should adhere to HTML standard attributes and types, such as type, disabled, aria-* attributes, and the onClick event handler.

Bad example
Implementations that pass only custom values to onClick event handlers significantly reduce maintainability and extensibility. Deviating from standard HTML attributes and event types can cause problems during future extensions.

// BAD: Button with missing HTML attributes or invalid type
type Props = {
  label: string;
  // Missing React.MouseEventHandler<HTMLButtonElement>
  onClick?: (value: string) => void;
  value?: string;
};

export const BadButton: React.FC<Props> = ({ label, onClick, className, value }) => {
  return (
    <button
      // Missing HTML type/disabled/aria-*
      className="inline-flex items-center rounded-md bg-blue-600 px-4 py-2 text-white"
      onClick={() => onClick?.(value ?? label)}
    >
      <span>{label}</span>
    </button>
  );
};
Enter fullscreen mode Exit fullscreen mode

Examples of improvements
HTML attributes are passed through as-is, and event handlers use standard types.

import React from "react";

type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
  variant?: "primary" | "secondary";
};

export const Button: React.FC<ButtonProps> = ({ className, variant = "primary", ...rest }) => {
  const base = "inline-flex items-center justify-center rounded-md px-4 py-2 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50";
  const style =
    variant === "primary"
      ? "bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-600"
      : "bg-gray-200 text-gray-900 hover:bg-gray-300 focus:ring-gray-400";
  return (
    <button className={[base, style, className].filter(Boolean).join(" ")} {...rest} />
  );
};

<Button type="submit" value="hello" onClick={(e) => console.log(e.currentTarget.value)} />;
Enter fullscreen mode Exit fullscreen mode

Top comments (0)