Стилизованные компоненты, отображающие стилизованный тег на основе реквизитов

#reactjs #typescript #styled-components #tsx

Вопрос:

Я создаю приложение и хочу иметь первичные, вторичные и третичные кнопки, я не хотел создавать 3 отдельных компонента, которые были бы такими же, но с другим компонентом в стиле, поэтому я хотел условно отобразить соответствующий тег, как в приведенном ниже коде, но я получаю сообщение об ошибке Тип элемента JSX «Стили кнопок» не имеет никаких сигнатур конструкции или вызова. Что я делаю не так? Спасибо

 import React from "react";
import styled from "styled-components";

const PrimaryStyles = styled.button`
  width: 26rem;
  height: 5rem;
  background-image: ${({ theme }) => theme.gradients.ry};
  border: none;
  border-radius: 4px;
  color: ${({ theme }) => theme.black};
  font-size: 2rem;
  box-shadow: 3px 3px 30px ${({ theme }) => theme.red   "70"};
  cursor: pointer;
  padding: 0 1rem;
`;

const SecondaryStyles = styled.button``;

const TertiaryStyles = styled.button`
  border: none;
  background: none;
  color: ${({ theme }) => theme.grey};
`;

interface IProps {
  type: "button" | "reset" | "submit";
  children: React.ReactNode;
  onClick: React.MouseEventHandler<HTMLButtonElement>;
  primary?: boolean;
  secondary?: boolean;
  tertiary?: boolean;
}
export const Button: React.FC<IProps> = ({
  children,
  onClick,
  type,
  primary = true,
  secondary,
  tertiary,
}) => {
  const ButtonStyles = primary
    ? PrimaryStyles
    : secondary
    ? SecondaryStyles
    : tertiary
    ? TertiaryStyles
    : null;
  return (
    <ButtonStyles type={type} onClick={onClick}>
      {children}
    </ButtonStyles>
  );
};

 

Ответ №1:

Это из-за такой логики:

 const ButtonStyles = primary
    ? PrimaryStyles
    : secondary
    ? SecondaryStyles
    : tertiary
    ? TertiaryStyles
    : null;
 

Если это не primary так , secondary или tertiary так будет null . Таким образом, ваш код будет настроен ButtonStyles как NULL , и тогда вы не сможете этого сделать:

  return (
    <ButtonStyles type={type} onClick={onClick}>
      {children}
    </ButtonStyles>
  );
 

Решением этой проблемы является удаление NULL опции, что-то вроде:

 const ButtonStyles = primary
    ? PrimaryStyles
    : secondary
    ? SecondaryStyles
    : TertiaryStyles;
 

Другой подход, чтобы избежать троичного условного оператора, состоял бы в том, чтобы сделать что-то вроде этого:

  1. Создайте объект, содержащий 3 варианта стилей:
 interface IButtonStyles {
  [key: string]: StyledComponent<"button", any, {}, never>;
}

const buttonStyleTypes: IButtonStyles = {
  primary: PrimaryStyles,
  secondary: SecondaryStyles,
  tertiary: TertiaryStyles,
};
 
  1. Измените свой IP-адрес на что-то подобное:
 interface IProps {
  type: "button" | "reset" | "submit";
  children: React.ReactNode;
  onClick: React.MouseEventHandler<HTMLButtonElement>;
  styleType?: string;
}
 
  1. Компонент кнопки для этого:
 const Button: React.FC<IProps> = ({
  children,
  type,
  styleType = "primary",
}) => {

  const ButtonStyles = buttonStyleTypes[styleType];

  return <ButtonStyles type={type}>{children}</ButtonStyles>;
};
 
  1. И, наконец, вы можете создать кнопку следующим образом:
 <Button type={"button"}>primary</Button>
<Button type={"button"} styleType='secondary'>secondary</Button>
<Button type={"button"} styleType='tertiary'>tertiary</Button>