ReactコンポーネントをAstroコンポーネントに書き換える際の、クラス名の取り扱いについて

すでにCreate React AppやVite、Next.jsなどでReactアプリとして構築しているものを、Astroにマイグレーションさせてみています。 その中で、「動的なクラス名の設定方法」が大きく異なる様子でし […]

広告ここから
広告ここまで

目次

    すでにCreate React AppやVite、Next.jsなどでReactアプリとして構築しているものを、Astroにマイグレーションさせてみています。

    その中で、「動的なクラス名の設定方法」が大きく異なる様子でしたので、簡単に紹介します。

    Reactではライブラリを利用して動的にクラス名を設定する

    Reactでは、classnamesclsxなどのライブラリを使って動的にクラス名を設定します。

    import clsx from 'clsx'
    
    <div  className={clsx('relative px-4 sm:px-8 lg:px-12', props.className)} >

    Astroでは、テンプレートディレクティブを利用する

    一方Astroでは、class:listディレクティブを使うことで、動的にクラス名が設定できます。

    <div class:list={['relative px-4 sm:px-8 lg:px-12', Astro.props.class]}>

    clsxなどを使うこともできますが、せっかくなのでclass:listに変更して依存ライブラリを減らしましょう。

    Before / After

    簡単なBefore / Afterを用意してみました。

    親コンポーネントからクラス名を追加で設定できるコンポーネントを想定しています。

    import clsx from 'clsx'
    
    function OuterContainer({ className, children, ...props }) {
      return (
        <div className={clsx('sm:px-8', className)} {...props}>
          <div className="mx-auto max-w-7xl lg:px-8">{children}</div>
        </div>
      )
    }

    Astroでは次のように実装します。

    ---
    
    const {class: className, ...props } = Astro.props
    ---
    
    <div class:list={['sm:px-8', className]} {...props}>
        <div class="mx-auto max-w-7xl lg:px-8"><slot></slot></div>
    </div>

    変更点としては、

    • clsxがなくなった
    • classNameclassに変わった
    • childrenから<slot></slot>に変わった

    があります。

    classの取り扱いに注意

    一つハマったのが、{...props}class:listを利用するケースです。

    <div class:list={['hello-world', Astro.props.class]} {...Astro.props}></div>

    この要素を、<Component class="bye"></Component>のように使った場合、...Astro.props側で渡されたclassが勝ちます。

    <div class='bye'></div>

    ...propsする場合は、class以外の値を渡すようにしましょう。

    ---
    const {class: className, ...props } = Astro.props
    ---
    <div class:list={['hello-world', class]} {...props}></div>

    参考資料

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark