web-dev-qa-db-fra.com

Comment ajouter du style - comme une marge - pour réagir composant?

Donc, attendez-vous à deux composants simples que j'ai construits:

import {Input} from 'semantic-ui-react';
import {Select} from 'semantic-ui-react';

const CategoriesDropdown = ({categories, onCategorySelected, selectedCategory}) => {
    const handleChange = (e, {value})=>{
        onCategorySelected(value);
    };
    return (
        <Select placeholder="Select category" search options={categories} onChange={handleChange} value={selectedCategory} />
    );
};

const IdentifiersInput = ({identifiers, onIdentifiersChanged}) => {
    return (
        <Input placeholder="Enter identifiers..." value={identifiers} onChange={onIdentifiersChanged}/>
    );
};

Rien de spécial jusqu'à présent.

Mais maintenant, je construis un autre composant qui affiche ces deux éléments dans une rangée de flexbox:

        <Box>
            <CategoriesDropdown categories={categories} selectedCategory={selectedCategoryId}
                           onCategorySelected={this.selectCategory}/>
            <IdentifiersInput identifiers={identifiers} onIdentifiersChanged={this.changeIdentifiers}/>
        </Box>

Malheureusement, ils sont tous deux affichés l'un à côté de l'autre sans aucune marge entre eux. 

Habituellement, je voudrais simplement ajouter un style margin-left au deuxième élément, mais comme il s'agit d'un composant React, cela ne fonctionne pas. Utiliser style={{marginLeft: '20px'}} ne fonctionne pas aussi bien, car le composant IdentifiersInput ne l'utilise pas.
Je sais que je peux le réparer en procédant comme suit: <Input style={style} ... dans le composant IdentifiersInput.
Cependant, cela semble être un moyen très fastidieux d’atteindre cet objectif. Fondamentalement, je dois ajouter cela à chaque composant que j'écris.
Il est évident que je dois rater quelque chose . Comment suis-je censé appliquer de telles propriétés CSS de mise en page aux composants React?

2
Daniel Hilgarth

Je pense que je comprends.

1) L'application de CSS directement aux composants React ne fonctionne pas - je peux le confirmer.

2) Passer des accessoires aux éléments de bas niveau est fastidieux, confirmé mais viable.

Avis hasMargin prop:

<Box>
  <CategoriesDropdown
    categories={categories}
    selectedCategory={selectedCategoryId}
    onCategorySelected={this.selectCategory}
  />
  <IdentifiersInput
    identifiers={identifiers}
    onIdentifiersChanged={this.changeIdentifiers}
    hasMargin
  />
</Box>

Entrée possible:

const IdentifiersInput = ({identifiers, onIdentifiersChanged, className, hasMargin }) => {
  return (
    <Input
      className={className}
      placeholder="Enter identifiers..."
      value={identifiers}
      onChange={onIdentifiersChanged}
      style={hasMargin ? ({ marginLeft: '0.8rem' }) : ({})}
    />
  );
};

NOTE: je n'aime pas le style autant que j'aime ajouter une classe supplémentaire car les classes peuvent être ajustées via des requêtes multimédia:

const IdentifiersInput = ({identifiers, onIdentifiersChanged, className, hasMargin }) => {
  const inputPosition = hasMargin ? `${className} margin-sm` : className
  return (
    <Input
      className={inputPosition}
      placeholder="Enter identifiers..."
      value={identifiers}
      onChange={onIdentifiersChanged}
    />
  );
};

Si vous trouvez inputPosition trop verbeux comme indiqué ci-dessus:

className={hasMargin ? `${className} margin-sm` : className}

3) Vous pouvez le réaliser en utilisant un composant diviseur, sacrigieux mais rapidement efficace 

<Box>
  <CategoriesDropdown
    categories={categories}
    selectedCategory={selectedCategoryId}
    onCategorySelected={this.selectCategory}
  />
  <div className="divider" />
  <IdentifiersInput
    identifiers={identifiers}
    onIdentifiersChanged={this.changeIdentifiers}
  />
</Box>

Vous pouvez utiliser des requêtes multimédia et contrôler le remplissage à tout point d'arrêt, si vous le souhaitez. 

4) Les pseudo-éléments ou pseudo-classes CSS, je ne vois aucune mention d'eux dans les réponses jusqu'à présent.

Habituellement, lorsque vous avez une collection aléatoire d’éléments du DOM, vous pouvez calculer de manière CSS en les plaçant à la position correcte. La liste des pseudo-classes disponibles se trouve dans ce lien MDN. Honnêtement, il est utile de simplement les regarder et de raisonner sur les combinaisons possibles.

Mon problème actuel est que je ne sais pas ce qu'il y a dans <Box />, à part qu'il y a probablement un div avec display: flex; dessus. Si tout ce que nous devons continuer est que et que la division s'appelle <div className="Box">, peut-être qu'un CSS comme celui-ci va résoudre ce problème:

.Box {
  display: flex;
}

.Box:first-child {
  margin-right: 0.8rem;
}

C'est pourquoi il est extrêmement important de savoir exactement ce que les éléments environnants seront ou pourront être, et quels classes/ID CSS se trouvent à proximité. Nous essayons fondamentalement d’attacher quelque chose et d’identifier correctement l’enfant de gauche dans Box et d’ajouter une marge à sa droite, ou de cibler le bon enfant et d’ajouter une marge à la gauche de celui-ci (ou, en fonction de tout, de cibler les deux et de scinder le marge sur les deux).

N'oubliez pas qu'il existe aussi ::before et ::after. Vous êtes invité à faire preuve de créativité et à trouver une solution qui implique position:relative et position: absolute et n’ajoute aucune balise.

Je vais laisser ma réponse comme ça pour le moment, parce que je pense que vous avez déjà pensé aux pseudo-sélecteurs, ou que vous trouverez rapidement quelque chose qui fonctionne :)

Cela ou le diviseur est en fait tout à fait viable. Le fait que vous puissiez utiliser les requêtes de média vous évite les soucis de gestion future ou d’évolutivité des composants. Je ne dirais pas la même chose à propos de <div style={{}} />.

2
agm1984

Lorsque votre composant se spécialise dans un autre composant, il peut être judicieux de transmettre tous les accessoires que votre wrapper ne prend pas en charge, au composant encapsulé. Sinon, vous perdrez la possibilité d'utiliser l'API du composant <Input> d'origine, y compris en lui passant des styles:

const IdentifiersInput = ({identifiers, onIdentifiersChanged, ...props}) = (
    <Input 
        {...props}
        placeholder="Enter identifiers..." 
        value={identifiers} 
        onChange={onIdentifiersChanged}
    />
);

Il peut y avoir des cas valides dans lesquels vous souhaitez explicitement empêcher les utilisateurs de pouvoir transmettre des accessoires au composant encapsulé, mais cela ne me ressemble pas du tout.

Je dois clairement manquer quelque chose ici. Comment suis-je censé postuler ces propriétés CSS de mise en page pour faire réagir les composants?

Tu n'as rien manqué. Un composant de réaction n'a aucun moyen générique d'être stylé car il ne s'agit pas d'un élément DOM. Il peut avoir une représentation DOM très compliquée et imbriquée ou aucune représentation. En tant que concepteur du composant, vous devez donc à un moment donné décider à quel endroit les styles, les identifiants et les noms de classe doivent être appliqués. Dans votre cas, il est aussi facile de passer ces accessoires et de laisser le <Input> et le <Select>component décider. Je trouve cela assez élégant plutôt que fastidieux.

1
trixn

Je vois plusieurs façons de le faire, mais le plus simple que je vois serait de passer un className à IdentifiersInput comme ceci:

<IdentifiersInput className="marginLeft" identifiers={identifiers} onIdentifiersChanged={this.changeIdentifiers}/>

Inside IdentifiersInput Je voudrais juste définir cette classe à l'entrée:

const IdentifiersInput = ({identifiers, onIdentifiersChanged, className}) => {
return (
    <Input className={className} placeholder="Enter identifiers..." value={identifiers} onChange={onIdentifiersChanged}/>
);
};

L'élément Input de Semantic UI peut recevoir un className prop . J'utiliserais alors simplement CSS ou SCSS pour ajouter des styles à cette classe particulière. Dans ce cas, la marge que vous voulez.

0
José Del Valle