ReactコンポーネントをAstroコンポーネントに書き換える際の、クラス名の取り扱いについて
すでにCreate React AppやVite、Next.jsなどでReactアプリとして構築しているものを、Astroにマイグレーションさせてみています。 その中で、「動的なクラス名の設定方法」が大きく異なる様子でし […]
広告ここから
広告ここまで
目次
すでにCreate React AppやVite、Next.jsなどでReactアプリとして構築しているものを、Astroにマイグレーションさせてみています。
その中で、「動的なクラス名の設定方法」が大きく異なる様子でしたので、簡単に紹介します。
Reactではライブラリを利用して動的にクラス名を設定する
Reactでは、classnames
やclsx
などのライブラリを使って動的にクラス名を設定します。
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
がなくなったclassName
がclass
に変わった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>