I have created a Button component with React and I would like it to have a different color depending on wether it receives a boolean prop or not in the parent component.
I have created the type "ButtonProps" and passed it to my ButtonElement created using styled-components.
Below my code:
import styled from "styled-components";
type ButtonProps = {
title: string;
onClickEvent: (e: React.MouseEvent) => void;
secondary?: boolean;
};
const ButtonElement = styled.button<ButtonProps>`
font-size: 1em;
margin: 1em;
padding: 0.45em 1em;
border: 2px solid #c1511d;
border-radius: 3px;
color: ${(props) => (props.secondary ? "red" : "#c1511d")};
text-transform: uppercase;
background-color: white;
cursor: pointer;
&:hover {
color: white;
background-color: #c1511d;
}
`;
const Button: React.FC<ButtonProps> = ({ title, onClickEvent }) => {
return <ButtonElement onClick={onClickEvent}>{title}</ButtonElement>;
};
export default Button;
Typescript shows there in an error by underlying the ButtonElement
after the return inside the React.FC
. The error is
No overload matches this call
What am I doing wrong?
CodePudding user response:
A closer look at the error message shows that:
Overload 1 of 2, '(props: [...]): ReactElement<...>', gave the following error.
Type '[...]' is missing the following properties from type '{[...]}': title, onClickEvent
The issue is that styled.button<ButtonProps>
builds a styled component which expects all ButtonProps
properties as props, hence the mandatory title
and onClickEvent
props, but when you call it, you do not pass these props: <ButtonElement onClick={onClickEvent}>
You just need to build a styled component that may receive the secondary
prop (which you use for styling), e.g. with TypeScript Pick
built-in utility type:
styled.button<Pick<ButtonProps, "secondary">>
And then do no forget to pass that prop to the styled component:
const Button: React.FC<ButtonProps> = ({
title,
onClickEvent,
secondary
}) => {
return <ButtonElement
onClick={onClickEvent}
secondary={secondary} // Pass the prop for extra styling
>{title}</ButtonElement>;
};