Astro アイランドの React コンポーネントに class 名を props で渡す Tips
はじめに
Astro テンプレート内に配置した React コンポーネントに class 属性を props で渡そうとしてハマったメモです。
Astro には入門したばかりなので、用語含め間違いがあればご指摘ください 🙏
⚠️ Astro から class 属性で React にクラス名を渡しても受け取れない
Astro のテンプレートでは class 名は通常の HTML と同じで class="foo" なので、見た目を揃えたくて React コンポーネントにも class="" でクラス名を渡そうとしたが常に undefined になってしまった
type MyComponentProps = {
class?: string;
};
export function MyComponent({ class: className }: MyComponentProps) {
return (
<div className={className}>...</div>
);
}
---
import { MyComponent } from '@/components/MyComponent';
---
<main>
<MyComponent client:load class="foo" />
</main>
class 属性で Astro から React の <MyComponent /> に props としてクラス名を渡そうとしているが props.class は常に undefined になってしまう
📝 class React 単体では警告が出るが string として値が渡される
React では className を使うべきだが誤って class を使った場合、警告は出るものの string として値が渡される (class がそもそも JavaScript の予約語なので使い方としてよくはない)
export function App() {
return <MyComponent class="foo" />;
}
=> Warning: Invalid DOM property `class`. Did you mean `className`?
🚀 Astro は React に class で className を渡そうとするとサポート外のプロパティとして undefined にする
🚨 This even works for class, which is not supported by React. 🚨
Differences between Astro and JSX
Astro component syntax is a superset of HTML. It was designed to feel familiar to anyone with HTML or JSX experience, but there are a couple of key differences between.astrofiles and JSX.
In Astro, you use the standardkebab-caseformat for all HTML attributes instead of thecamelCaseused in JSX. This even works forclass, which is not supported by React.
cf. Astro Template expressions reference - Differences between Astro and JSX
Astro は React コンポーネントに class を渡す際に className に変換してくれるわけではない。
React ではサポートされてないプロパティとして切り捨てているために undefined になるのだと思われる (明確な仕様を見つけられなかった)
Astro から React Component にクラス名を渡す際に class を自動的に className に変換したいという issue も上がっていたが止まっているっぽい。
個人的に class で渡しているものが className という別の名前で受け取れるのは気持ち悪いので、自動変換は不要かなと感じた。 (class で渡して class で受け取れるなら理解できるが)
なので、Astro から React コンポーネントにクラス名を渡したいときは、素直に className を使うのが良い
type MyComponentProps = {
- class?: string;
+ className?: string;
};
- export function MyComponent({ class: className }: MyComponentProps) {
+ export function MyComponent({ className }: MyComponentProps) {
return (
<div className={className}>...</div>
);
}
- <MyComponent client:load class="foo" />
+ <MyComponent client:load className="foo" />
まとめ
- そもそも React では
classでクラス名を渡すのは間違った使い方である - React の世界では Warning が出るもの
classNameとして扱ってくれるが、Astro は React にはclassでプロパティは渡せないものと判断するので、常にundefinedになる- class を className に自動変換する issue もあったが止まっている
https://github.com/withastro/astro/issues/448
- class を className に自動変換する issue もあったが止まっている
- 結論: React Component にクラス名を渡すときは
classNameを使う
✌️₍ᐢ.ˬ.ᐢ₎✌️ happy!
Discussion