Alors, 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 d'extraordinaire jusqu'à présent.

Mais maintenant, je construis un autre composant qui affiche ces deux dans une ligne flexbox:

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

Malheureusement, ils sont tous deux affichés côte à côte sans aucune marge entre les deux.

Habituellement, j'ajouterais simplement un style margin-left au deuxième élément, mais comme il s'agit d'un composant React, cela ne fonctionne pas. L'utilisation de 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 faisant ceci: <Input style={style} ... à l'intérieur du 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.
Je dois clairement manquer quelque chose ici . Comment suis-je censé appliquer ces propriétés CSS de mise en page aux composants React?

8
Daniel Hilgarth 14 avril 2018 à 00:30

3 réponses

Meilleure réponse

Je pense que je comprends.

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

2) La transmission des accessoires aux éléments de bas niveau est fastidieuse, confirmée mais viable.

Remarquez hasMargin accessoire:

<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 autant le style que j'aime ajouter une classe supplémentaire car les classes peuvent être ajustées via des requêtes mé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 l'accomplir en utilisant un composant diviseur, sacreligieux 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édias et contrôler le remplissage à n'importe quel point d'arrêt si vous le souhaitez.

4) Pseudo-éléments CSS ou pseudo-classes, 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 DOM, vous pouvez calculer un moyen à l'aide de CSS pour les placer dans la bonne position. 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 potentielles.

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 avons à faire, c'est que le div est appelé <div className="Box">, peut-être que certains CSS comme celui-ci le corrigeront:

.Box {
  display: flex;
}

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

C'est pourquoi il est extrêmement important de savoir exactement quels seront ou peuvent être les éléments environnants, et exactement quelles classes / ID CSS se trouvent à proximité. Nous essayons fondamentalement de nous accrocher à quelque chose et d'identifier correctement l'enfant gauche dans Box et d'ajouter une marge à droite de celui-ci, ou de cibler l'enfant droit et d'ajouter une marge à gauche de celui-ci (ou, selon tout, cibler les deux et diviser le supplémentaire marge sur les deux).

N'oubliez pas qu'il y a aussi ::before et ::after. Vous êtes invités à faire preuve de créativité et à trouver une solution qui implique position:relative et position: absolute et n'ajoute aucun balisage.

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

Cela ou le séparateur est en fait tout à fait viable. Le fait que vous puissiez utiliser des requêtes multimédias vous évite de vous soucier de la gestion future ou de l'évolutivité des composants. Je ne dirais pas la même chose de <div style={{}} />.

7
agm1984 14 avril 2018 à 04:11

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

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

Inside IdentifiersInput Je voudrais simplement définir cette classe sur l'entrée:

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

L'élément Input de l'interface utilisateur sémantique peut recevoir un accessoire className. J'utiliserais alors simplement CSS ou SCSS pour ajouter des styles à cette classe particulière. Dans ce cas, la marge souhaitée.

0
José Del Valle 13 avril 2018 à 22:24

Comme votre composant se spécialise dans un autre composant unique, il serait judicieux de passer tous les accessoires dont votre wrapper ne tient pas compte au composant enveloppé. 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 où vous voulez explicitement empêcher les utilisateurs de pouvoir passer des accessoires au composant encapsulé, mais cela ne ressemble pas à l'un d'eux.

Je dois clairement manquer quelque chose ici. Comment suis-je censé appliquer ces propriétés CSS de mise en page aux composants React?

Vous n'avez rien manqué. Un composant react 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 du tout. Donc, à un moment donné, en tant que concepteur du composant, vous devez décider où les styles, les identifiants et les noms de classe doivent être appliqués. Dans votre cas, c'est aussi simple que de passer ces accessoires et de laisser les composants <Input> et <Select> décider. Je trouve cela plutôt élégant que fastidieux.

2
trixn 13 avril 2018 à 23:31