1
votes

Comment combiner des InputProps existants avec des InputProps supplémentaires dans un composant enfant

J'ai écrit une version personnalisée de material-ui TextField (appelons-le CustTextField1) avec un style personnalisé. Je souhaite développer une autre personnalisation appelée CustTextField2 basée sur le style de CustTextField1. J'ai appliqué InputProps à CustTextField1 et je veux que ceux-ci soient utilisés dans CustTextField2 avec quelques InputProps supplémentaires que j'applique là. Voici les parties pertinentes du code. Les InputProps appliqués à CustTextField2 apparaissent (c'est-à-dire l'icône en forme d'œil de mot de passe) mais semblent remplacer les InputProps déjà définis dans CustTextField1. Toute aide sur la façon de combiner les deux serait très appréciée.

function CustTextField2(props) {
  return (
    <CustTextField1
    InputProps={{    
        endAdornment: (
                    <InputAdornment position="end">
                        <IconButton>
                            {showPassword ? <Visibility/> : <VisibilityOff/>}
                        </IconButton>
                    </InputAdornment>
                ),
          ...props.InputProps
        }
      }}

      {...props}
    />
)
}
function CustTextField1(props) {
  return (
    <TextField
      InputProps={{     
        disableUnderline: true,
        classes: {
          root: textFieldStyle.rootInputStyle,
          focused: textFieldStyle.focused,
          disabled: textFieldStyle.disabled,
          error: textFieldStyle.error
        }
      }}

      {...props}
    />
)
}

J'aimerais que le style InputProps dans CustTextField1 soit combiné avec le style InputProps supplémentaire dans CustTextField2 .

!! MISE À JOUR !!

Code Sandbox (problème d'origine) - https://codesandbox.io/s/fervent-smoke-g8nsb

Code Sandbox (Solution) avec nos sincères remerciements pour le message de toutpt ci-dessous - https: // codesandbox. io / s / stoïque-mclean-9kh1r


0 commentaires

3 Réponses :


1
votes

Vous devez toujours vous occuper de la composition lorsque vous souhaitez hériter. Vous devez donc d'abord vous occuper des accessoires que vous souhaitez remplacer.

Dans l'exemple suivant, CustTextField1 s'occupera d'InputProps pour ajouter la base et laisser l'utilisateur les remplacer. Mais comme il y a les classes qui sont aussi un objet, je dois m'en occuper.

InputProps={} // the one define by CustTextField1
... 
InputProps={} // the one define by CustTextField2

Dans votre exemple, vous ne déstructurez pas les accessoires Ainsi, lorsque vous étendez les accessoires, vous remplacez complètement InputProps .

 InputProps={}
 {...props}

Donc, si props contient InputProps code> vous le faites deux fois:

function CustTextField1({ InputProps, ...props }) {
    const iprops = Object.assign({
        disableUnderline: true,
    }, InputProps, {
        classes: Object.assign({
            root: textFieldStyle.rootInputStyle,
            focused: textFieldStyle.focused,
            disabled: textFieldStyle.disabled,
            error: textFieldStyle.error,
        }, InputProps.classes || {})
    });
    return <TextField InputProps={iprops} {...props} />;
}


4 commentaires

Exemple de codesandbox utilisant votre solution: codesandbox.io/s/stoic-mclean-9kh1r


Oui ça l'a fait. Merci beaucoup.


Excellent ! veuillez valider la réponse en utilisant le bouton cocher sous le vote dans ce cas;)


Pardon. Réponse validée maintenant :)



0
votes

Vous déclarez deux fois les mêmes accessoires, donc les derniers appliqués écraseront les précédents. Si vous vous donnez déjà la peine de créer 2 composants séparés, il serait plus judicieux de commencer le 2ème à partir de zéro sans utiliser le premier.

Cependant, je pense qu'une meilleure solution consiste à utiliser un seul composant et à ajouter un accessoire pour basculer la configuration supplémentaire souhaitée:

function CustTextField(props) {
  let inputProps = {
    disableUnderline: true,
    classes: {
      root: textFieldStyle.rootInputStyle,
      focused: textFieldStyle.focused,
      disabled: textFieldStyle.disabled,
      error: textFieldStyle.error
    },
    endAdornment: props.adornment ? (
      <InputAdornment position="end">
        <IconButton> {true ? <Visibility /> : <VisibilityOff />}</IconButton>
      </InputAdornment>
    ) : null
  };

  return <TextField InputProps={inputProps} {...props} />;
}

....

<CustTextField adorned={true}/>


0 commentaires

1
votes

L'injection Prop dans React fonctionne de manière similaire à la façon dont les objets Javascript sont gérés, c'est-à-dire que la clé correspondante suivante remplace la clé précédente. Dans le contexte de l'objet, ce que vous faites est de remplacer les InputProps par les InputProps provenant de this.props . pour votre cas d'utilisation spécifique, vous remplacez chaque accessoire en plaçant {... this.props} avant de combiner InputProps dans CustTextField2 .

function CustTextField2(props) {
  return (
    <CustTextField1
    {...props}
    InputProps={{    
        endAdornment: (
                <InputAdornment position="end">
                    <IconButton>
                        {showPassword ? <Visibility/> : <VisibilityOff/>}
                    </IconButton>
                </InputAdornment>
            ),
      ...props.InputProps
    }
  }}
/>
)
}

de cette façon, vous passerez tous les accessoires avec le prop InputProps remplacé à votre goût.


1 commentaires

Cela fait passer les InputProps de CustTextField1 mais l'endAdornment n'est pas ajouté. C'est donc mon problème initial, mais maintenant l'inverse.