Si tengo el siguiente botón con un predeterminado

export interface IButton {
  variant: 'action' | 'secondary';
}

export const Button = styled('button')<IButton>`
  background-color: #fff;

  ${props =>
    props.variant === 'action' &&
    css`
      color: blue;
    `};

  ${props =>
    props.variant === 'secondary' &&
    css`
      color: gray;
    `};
`;

Button.defaultProps = {
  variant: 'action',
};

¿Hay alguna forma de escribirlo? Cuando trato de usarlo como

<Button>Hello</Button>

El mecanografiado se queja de no pasar la variante, ¿hay alguna manera de escribir defaultProps con componentes con estilo?

2
donzul 7 sep. 2018 a las 19:41

3 respuestas

La mejor respuesta

El problema es que el soporte de TypeScript 3.0 para defaultProps en la verificación de elementos JSX requiere que se declare el tipo de defaultProps en el componente. Mutar el defaultProps de un componente existente no funcionará, y no conozco ninguna buena manera de declarar el defaultProps en un componente generado por una función como styled. (En cierto modo, esto tiene sentido: la biblioteca crea un componente y no espera que lo modifique. Tal vez la biblioteca incluso se configura defaultProps para algún propósito interno). La solución de Kingdaro está bien, o puede usar un componente de envoltura:

const Button1 = styled('button')<IButton>`
  background-color: #fff;

  ${props =>
    props.variant === 'action' &&
    css`
      color: blue;
    `};

  ${props =>
    props.variant === 'secondary' &&
    css`
      color: gray;
    `};
`;

export class Button extends React.Component<IButton> {
  static defaultProps = {
    variant: 'action'
  };
  render() {
    return <Button1 {...this.props}/>;
  }
}
3
Matt McCutchen 9 sep. 2018 a las 22:45

Que yo sepa, esto aún no es posible, y desafortunadamente no está cubierto por el soporte defaultProps agregado en TS 3.0 (que solo se aplica a las clases de componentes normales, y creo funcional componentes). Otros se sienten libres de corregirme si me equivoco en esto.

Sin embargo, hay otras formas de escribirlo. Así es como suelo hacerlo:

export interface IButton {
  variant?: 'action' | 'secondary';
}

const variantStyles = {
  action: css`
    color: blue;
  `,
  secondary: css`
    color: gray;
  `,
};

export const Button = styled('button')<IButton>`
  background-color: #fff;
  ${props => variantStyles[props.variant || 'action']};
`;
1
kingdaro 7 sep. 2018 a las 17:40

Puedes lograr lo que quieres al desestructurar tus accesorios.

Parece que todavía tiene que informar a su componente sobre sus tipos de utilería. Para eso, solo pasa todos los accesorios sin destruirlos (ver el color de fondo a continuación).

import styled from "styled-components";

interface IProps {
  variant?: 'action' | 'secondary';
}

export const Button = styled.div`
  ${(props: IProps) => `background-color: #fff;`}
  ${({ variant = 'action' }) => variant === 'action' ? `color: blue;` : `color: gray;`}
`;
2
jackdbd 2 abr. 2019 a las 08:40