Maison  >  Questions et réponses  >  le corps du texte

Rendre les accessoires React facultatifs et requis dans TypeScript en fonction d'autres accessoires

J'ai un composant conteneur de boutons React qui renvoie un bouton normal, un bouton icône ou un bouton icône uniquement en fonction du type fourni par l'accessoire utilisé par l'utilisateur. Voici les définitions de types pertinentes pour ButtonContainer组件与Props : 

type ButtonWrapperProp = {
    label?:string;
    icon?:React.ReactNode;
    onClick:()=>void;
    type:'text'|'icon'|'iconOnly';

}

export const ButtonContainer = (props: ButtonWrapperProps) => {
    const {
        type = 'text',
        onClick,
        icon = <></>,
        label = '',
    } = props;

    const rendorButton = () => {
        switch (type) {
            case 'text':
                return (
                    <Button onClick={onClick}>{label}  <Button/>
                );

            case 'iconOnly':
                return (
                     <IconButton onClick={onClick}>
                       {icon}
                     </IconButton>
                );

            case 'icon':
                return (
                     <Button startIcon={icon}>
                       {label}
                     </Button>
                );

            default:
                return (
                    <Button onClick={onClick}>{label}  <Button/>
                );
        }
    };
    return <>{rendorButton()}</>;
};

Voici comment j'utilise le composant ButtonContainer :

<ButtonContainer type="iconOnly" onClick={onClick} icon={<DeleteIcon />}/>
<ButtonContainer type="text" onClick={onClick} label='Text button'/>
<ButtonContainer type="icon" onClick={onClick} label='Text and icon button' icon={<DeleteIcon />}/>

Dans le code ci-dessus, l'accessoire icône est facultatif car il n'est utilisé que pour les boutons d'icônes et les boutons normaux avec des icônes. Je souhaite que le accessoire d'icône soit facultatif uniquement si le type transmis par ButtonContainer est du texte et il devrait s'agir d'un accessoire obligatoire si le type transmis à ButtonContainer est une icône ou iconOnly.

P粉738046172P粉738046172398 Il y a quelques jours641

répondre à tous(1)je répondrai

  • P粉803444331

    P粉8034443312023-09-18 12:22:20

    Je choisirais d'utiliser Distinguish Union Type.

    L'attribut type agit comme un discriminateur, vous permettant de limiter ButtonWrapperProps aux membres du syndicat.

    Notez également que je peux rendre obligatoires les propriétés de chaque membre du syndicat, ce qui donne une expérience agréable lors de leur utilisation - TS est suffisamment intelligent pour indiquer quelles propriétés supplémentaires sont requises une fois le type défini.

    type TextButtonProps = {
      type:'text'
      label:string;
      onClick:()=>void;
    }
    
    type IconOnlyButtonProps = {
      type:'iconOnly'
      icon:React.ReactNode;
      onClick:()=>void;
    }
    
    type IconButtonProps = {
      type:'icon'
      icon:React.ReactNode;
      label:string;
      onClick:()=>void;
    }
    
    type ButtonWrapperProps = TextButtonProps | IconOnlyButtonProps | IconButtonProps;
    
    export const ButtonContainer = (props: ButtonWrapperProps) => {
      const renderButton = () => {
          switch (props.type) {
              case 'text':
                  return (
                      <Button onClick={props.onClick}>{props.label}  </Button>
                  );
    
              case 'iconOnly':
                  return (
                       <IconButton onClick={props.onClick}>
                         {props.icon}
                       </IconButton>
                  );
    
              case 'icon':
                  return (
                       <Button startIcon={props.icon}>
                         {props.label}
                       </Button>
                  );
          }
      };
      return <>{renderButton()}</>;
    };
    

    répondre
    0
  • Annulerrépondre