c8r/genのリファクタリング中に見つけたコード

まだ型を当てている最中。途中、おもしろい箇所を見つけた。 CSS in JSのライブラリとして、二種類あるのだけれど、それをうまく切り替えていた部分があった。

<!--truncate-->
  • paypal/glamorous
  • styled-components/styled-components

glamorousの方はもうメンテナンスされていないので、styled-componentsを使うほうが良いのだが、コード中に切り替えポイントがあった。

// createComponent.ts
const componentCreators: { [key: string]: (comp: any, lib: any) => React.ComponentClass } = {
  glamorous: ({ name, type, style, props, system = [] }: GlamorousOptions, lib: object) => {
    // todo: DRY up
    const tag = lib[type] || type
    const funcs = getFunctions(system)
    const Comp = glamorous(tag)(style, ...funcs)

    Comp.defaultProps = props
    Comp.displayName = name

    return Comp
  },
  'styled-components': ({ name, type, style, props, system = [] }: StyledOptions, lib: object) => {
    const tag = lib[type] || type
    const funcs = getFunctions(system)
    // @ts-ignore
    const Comp = styled(tag)([], style, ...funcs)

    Comp.defaultProps = props
    Comp.displayName = name

    return Comp
  },
}

使う側は、createComponentでwarpしておいて、

const createComponent = (opts: Options2) => (comp: ComponentConfig, lib: object): null | React.ComponentClass => {
  if (isExternal(comp)) {
    return null
  }
  if (isComposite(comp)) {
    return createComposite(comp, lib)
  }
  if (!comp.name || !comp.type || !comp.style) {
    return null
  }

  const library = opts.library || 'styled-components'
  // 利用するfunctionを指定する
  const sx = componentCreators[library]
  return sx(comp, lib)
}

オプションのフラグで使うライブラリを切り替える。 使う側は、Factoryメソッド自体を受けとって、それの内部実装を知らずにメソッドを利用することができるようになる。

const create = createComponent(opts)

なるほど〜。