Home > Software engineering >  TS doesn't see default props in React function component
TS doesn't see default props in React function component

Time:07-16

My code

interface ButtonProps {
  onClick?: () => void
}

const Button: FC<ButtonProps> = ({ onClick }) => {
  const wrapClick = () => {
    onClick() // TS2722: Cannot invoke an object which is possibly 'undefined'.
  }

  return <button onClick={wrapClick}>button</button>
}

Button.defaultProps = {
  onClick: () => {},
}

In this case, everything works

const Button: FC<ButtonProps> = ({ onClick }) => {
  const wrapClick = () => {
    onClick && onClick()
  }

  return <button onClick={wrapClick}>button</button>
}

and in this

const Button: FC<ButtonProps> = ({ onClick = () => {} }) => {
  const wrapClick = () => {
    onClick()
  }

  return <button onClick={wrapClick}>button</button>
}

Is there a way to use default props to solve this problem ? Since I have large components with a lot of properties.

CodePudding user response:

The onClick property in the props object is marked as optional by using a question mark, so we can't directly invoke the function.

To solve the error, use the optional chaining (?.) operator when calling the function.

import { FC } from "react";

interface ButtonProps {
  onClick?: () => void;
}

const Button: FC<ButtonProps> = ({ onClick }) => {
  const wrapClick = () => {
    onClick?.();
  };

  return <button onClick={wrapClick}>button</button>;
};

Button.defaultProps = {
  onClick: () => {}
};

export default Button;

Code Sandbox : DEMO

CodePudding user response:

Use the Non-null assertion operator (postfix !) to let TypeScript know your default onClick(): void is not null/undefined (which it thinks it is because of IButtonProps.onClick: () => void | undefined, which is used by Button (FC<IButtonProps>, FC<T>.defaultProps is of type T & { children?: Node } if I remember correctly)).

interface IButtonProps {
  onClick?: () => void;  // No event args?
}

const Button: FC<IButtonProps> = (props) => {
  const {
    onClick = Button.defaultProps.onClick!,
  } = props;

  const wrapClick = (/* No event args? */) => {
    onClick();
  };

  return <button onClick={wrapClick}>button</button>;
};

Button.defaultProps = {
  onClick: () => {},
};
  • Related