如何添加样式 - 如边距 - 来反应组件?

How to add style - like margin - to react component?

所以,期待我构建的两个简单组件:

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}/>
    );
};

到目前为止没什么特别的。

但是现在,我正在构建另一个在 flexbox 行中显示这两个组件的组件:

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

不幸的是,它们并排显示,中间没有任何空白。

通常,我会在第二个元素上添加一个 margin-left 样式,但因为它是一个 React 组件,所以这不起作用。使用 style={{marginLeft: '20px'}} 也不起作用,因为 IdentifiersInput 组件不使用它。
我知道我可以通过这样做来修复它:<Input style={style} ... inside the IdentifiersInput component.
但是,这似乎是实现此目标的一种非常乏味的方式。基本上,我必须将它添加到我正在编写的每个组件中。
我显然一定是遗漏了什么。我应该如何将这样的布局 CSS 属性应用于 React 组件?

我看到了几种方法,但我看到最简单的方法是像这样将 className 传递给 IdentifiersInput:

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

Inside IdentifiersInput 我只是将 class 设置为输入:

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

语义 UI 的输入元素可以接收 className 属性。 然后,我将只使用 CSS 或 SCSS 向特定 class 添加样式。在这种情况下,您想要的保证金。

由于您的组件专门用于另一个组件,因此最好将您的包装器不关心的任何道具传递给被包装的组件。否则,您将失去使用原始 <Input> 组件的 api 的能力,包括向其传递样式:

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

在某些情况下,您可能明确希望阻止用户将 props 传递给包装的组件,但在我看来这不像是其中之一。

I clearly must be missing something here. How am I supposed to apply such layout CSS properties to React components?

你没有错过任何东西。 React 组件没有通用的样式设置方式,因为它不是 DOM 元素。它可以有非常复杂的嵌套 DOM 表示或根本没有表示。所以在某些时候,作为组件的设计者,您必须决定样式、id 和 class 名称应该应用到哪里。在你的情况下,就像传递这些道具一样简单,让 <Input><Select> 组件决定。我觉得这很优雅而不是乏味。

我想我明白了。

1) 直接将 CSS 应用到 React Components 不起作用——我可以确认这一点。

2) 将 props 向下传递给低级元素是乏味的,已确认但可行。

通知hasMargin 道具:

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

可能的输入:

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

注意:我不喜欢样式,我喜欢添加额外的 class 因为 classes 可以通过媒体查询进行调整:

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

如果您发现 inputPosition 过于冗长,如上所示:

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

3) 您可以使用 divider 组件来完成它,虽然亵渎神明但效果迅速

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

如果需要,您可以在任何断点处使用媒体查询和控制填充。

4) CSS 伪元素或伪 classes,到目前为止我没有在答案中看到任何提及它们。

通常,当您有 DOM 个元素的随机集合时,您可以使用 CSS 计算出一种将它们整理到正确位置的方法。可用的伪 classes 列表在 MDN link 中。老实说,只看它们并推理可能的组合会有所帮助。

我目前的问题是我不知道 <Box /> 里有什么,除了它上面可能有一个 div 和 display: flex;。如果我们只需要继续,并且 div 被称为 <div className="Box">,也许像这样的 CSS 会修复它:

.Box {
  display: flex;
}

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

这就是为什么准确了解周围的元素将会或可能是什么,以及附近有哪些 CSS classes/IDs 是极其重要的原因。我们基本上是在尝试挂钩某些东西并正确识别 Box 中的左子节点并在其右侧添加边距,或者以右子节点为目标并在其左侧添加边距(或者根据所有情况,同时定位两个子节点并拆分附加的两者都有保证金)。

记住还有 ::before::after。欢迎发挥创意,找到涉及 position:relativeposition: absolute 且不添加任何标记的解决方案。

我暂时保留我的答案,因为我认为要么你已经考虑过伪选择器,要么你很快就会找到有用的东西:)

那个或 divider 实际上是相当可行的。您可以使用媒体查询这一事实使您不必担心组件的未来管理或可伸缩性。我不会对 <div style={{}} /> 说同样的话。