スタイルのコンポーネント、もう1回


UPD :
元来styled-components 図書館は2016年に登場した.その案は提案されたGlen Maddern . それはCSS-in-JS 解決策は、私の意見では、最も強力な部分は、JSではCSSではなく、小さなコンポーネントを高速作成する機能です.
次のスニペットを考えます.
<h1 style={{ fontSize: "1.5em", textAlign: "center", color: "palevioletred" }}>
  Hello World, this is my first styled component!
</h1>

const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

<Title>Hello World, this is my first styled component!</Title>;
このコードには意味論があります.あなたは簡単にそれがタイトルであると言うことができますh1 それは推測することが可能ですがdiv ?..).
スタイル付きコンポーネントなしで同じことを行うことができます.
const Title = ({ children }) => (
  <h1
    style={{ fontSize: "1.5em", textAlign: "center", color: "palevioletred" }}
  >
    {children}
  </h1>
);
しかし、それに直面しよう.スタイルのコンポーネントがどこにあるかは、それが自然に起こります.これは単純なバージョンです、それは小道具を通過しない、それは処理しませんref プロパティ.
A 11 Yときれいにスタイルのコンポーネントをペア.例えば、この代わりに:
<>
  <div
    role="button"
    aria-expanded={expanded}
    aria-controls={sectionId}
    id={labelId}
    className={styles.Label}
    onClick={() => onToggle && onToggle(index)}
  >
    {title}
    <span aria-hidden={true}>{expanded ? "" : ""}</span>
  </div>
  <div
    role="region"
    aria-labelledby={labelId}
    id={sectionId}
    hidden={!expanded}
    className={styles.Panel}
  >
    {expanded && (isFunction(children) ? children() : children)}
  </div>
</>
書くことができます
const Label = styled.div("Label");
Label.defaultProps = { role: "button" };

const Panel = styled.div("Panel");
Panel.defaultProps = { role: "region" };

<>
  <Label
    aria-expanded={expanded}
    aria-controls={sectionId}
    id={labelId}
    onClick={() => onToggle && onToggle(index)}
  >
    {title}
    <span aria-hidden={true}>{expanded ? "" : ""}</span>
  </Label>
  <Panel aria-labelledby={labelId} id={sectionId} hidden={!expanded}>
    {expanded && (isFunction(children) ? children() : children)}
  </Panel>
</>;
ニッカーじゃない?

代替案
この考えはとても人気があり、他の図書館でも写し出された.

CSSで
  • Emotion
  • JSS

  • のランタイムのCSS
  • Linaria

  • スタイルプロパティ
  • unstyled-components

  • CSSモジュール
  • css-modules-components
  • styled-style
  • css-to-js-loader

  • DIY
    スタイルを構成するコンポーネントの簡略化された実装を書きましょう.そこで始めましょう.
    const Title = ({ children }) => (
      <h1
        style={{ fontSize: "1.5em", textAlign: "center", color: "palevioletred" }}
      >
        {children}
      </h1>
    );
    
    1 ) propsを渡す必要があります.
    const Title = ({ children, ...props }) => (
      <h1
        style={{ fontSize: "1.5em", textAlign: "center", color: "palevioletred" }}
        {...props}
      >
        {children}
      </h1>
    );
    
    2 )取り扱いが必要ですref
    const Title = React.forwardRef(({ children, ...props }, ref) => (
      <h1
        style={{ fontSize: "1.5em", textAlign: "center", color: "palevioletred" }}
        ref={ref}
        {...props}
      >
        {children}
      </h1>
    ));
    
    3 )タグを設定可能にしましょうas プロパティ(is or use )
    const Title = React.forwardRef(({ children, as = "h1", ...props }, ref) =>
      React.createElement(
        as,
        {
          style: { fontSize: "1.5em", textAlign: "center", color: "palevioletred" },
          ...props,
          ref
        },
        children
      )
    );
    
    4 )スタイルをオーバーライドする方法を追加しましょう
    const Title = React.forwardRef(({ children, as = "h1", ...props }, ref) =>
      React.createElement(
        as,
        {
          ...props,
          style: {
            fontSize: "1.5em",
            textAlign: "center",
            color: "palevioletred",
            ...props.style
          },
          ref
        },
        children
      )
    );
    
    5 )コンポーネントを生成しましょう
    const styled = defaultAs =>
      React.forwardRef(({ children, as = defaultAs, ...props }, ref) =>
        React.createElement(
          as,
          {
            ...props,
            style: {
              fontSize: "1.5em",
              textAlign: "center",
              color: "palevioletred",
              ...props.style
            },
            ref
          },
          children
        )
      );
    
    const Title = styled("h1");
    
    6 )外部からデフォルトのスタイルを伝えましょう
    const styled = defaultAs => defaultStyles =>
      React.forwardRef(({ children, as = defaultAs, ...props }, ref) =>
        React.createElement(
          as,
          {
            ...props,
            style: {
              ...defaultStyles,
              ...props.style
            },
            ref
          },
          children
        )
      );
    
    const Title = styled("h1")({
      fontSize: "1.5em",
      textAlign: "center",
      color: "palevioletred"
    });
    
    7 )コンポーネントにディスプレイ名を追加する
    const styled = defaultAs => defaultStyles => {
      const component = React.forwardRef(
        ({ children, as = defaultAs, ...props }, ref) =>
          React.createElement(
            as,
            {
              ...props,
              style: {
                ...defaultStyles,
                ...props.style
              },
              ref
            },
            children
          )
      );
      component.displayName = `${defaultAs}💅`;
      return component;
    };
    
    プロパティに応じてカスタマイズ可能なメイクスタイル
    const isFunction = x => !!(x && x.constructor && x.call && x.apply);
    
    const styled = defaultAs => defaultStyles => {
      const component = React.forwardRef(
        ({ children, as = defaultAs, ...props }, ref) =>
          React.createElement(
            as,
            {
              ...props,
              style: {
                ...(isFunction(defaultStyles)
                  ? defaultStyles(props)
                  : defaultStyles),
                ...props.style
              },
              ref
            },
            children
          )
      );
      component.displayName = `${defaultAs}💅`;
      return component;
    };
    
    const Title = styled("h1")(() => ({
      fontSize: "1.5em",
      textAlign: "center",
      color: "palevioletred"
    }));
    
    非HTMLプロパティをフィルタリングします.propTypes :
    const filterObject = (rest, shouldForwardProp) =>
      Object.keys(rest)
        .filter(shouldForwardProp)
        .reduce((obj, key) => {
          obj[key] = rest[key];
          return obj;
        }, {});
    
    const styled = defaultAs => defaultStyles => {
      const component = React.forwardRef(
        ({ children, as = defaultAs, ...props }, ref) =>
          React.createElement(
            as,
            {
              ...(component.propTypes
                ? filterObject(props, key =>
                    Object.keys(component.propTypes).includes(key)
                  )
                : props),
              style: {
                ...(isFunction(defaultStyles)
                  ? defaultStyles(props)
                  : defaultStyles),
                ...props.style
              },
              ref
            },
            children
          )
      );
      component.displayName = `${defaultAs}💅`;
      return component;
    };
    
    10)ボーナス.使いましょうProxy 最初の関数の代わりに:
    const styled = Proxy(
      {},
      {
        get: (_, defaultAs, __) => defaultStyles => {
          const component = React.forwardRef(
            ({ children, as = defaultAs, ...props }, ref) =>
              React.createElement(
                as,
                {
                  ...(component.propTypes
                    ? filterObject(props, key =>
                        Object.keys(component.propTypes).includes(key)
                      )
                    : props),
                  style: {
                    ...(isFunction(defaultStyles)
                      ? defaultStyles(props)
                      : defaultStyles),
                    ...props.style
                  },
                  ref
                },
                children
              )
          );
          component.displayName = `${defaultAs}💅`;
          return component;
        }
      }
    );
    
    const Title = styled.h1({
      fontSize: "1.5em",
      textAlign: "center",
      color: "palevioletred"
    });
    
    今、あなたは何が内部知っている!