LoginSignup
2
2

More than 3 years have passed since last update.

emotion (emotion.js) のStyled Componentsで作成した要素にカスタム属性を渡したくなったら (shouldForwardProp)

Posted at

今日ハマったのでメモ。

Reactはバージョン16から要素に好きに属性を生やせます

Reactはバージョン16からカスタム属性の利用を認めています。

たとえば、下記のような属性指定ですね。

<a mycustomattr="customvalue">foobar</a>

上記の場合だときちんと mycustomattr="customvalue" が実際のDOMにレンダリングされます。

もともとReactでは、HTML公認のカスタム属性である data-** や、幅広い語彙を持つ aria-** は利用を認められていたのですが、その他の自作の属性、あるいはHTML5でいなくなった古い属性(e.g. <td> 要素の align 属性)は、カスタム属性が使えないと表現できません。

emotionのStyled Componentsはそのままだとカスタム属性をはたき落とします

そして本題ですが、タイトルの通りemotionのStyled Componentsは、デフォルトでカスタム属性をはたき落とします。

たとえば、

const CustomElem = styled.div`
  color: red;
`

// @ts-ignore
return <CustomElem mycustomattr="customvalue">Hello</CustomElem>

(@ts-ignore はTypeScriptさんが mycustomattr なんてないよ!とエラーを出すのを抑制するために入れています。JSの人は要りません。)

上記のコードだと mycustomattr がはたき落とされます。基本的には、is-prop-validという実装に従って、HTMLに無さそうな属性は自動的に消してくれるようです。

今までのReactであれば、存在しない属性を渡すと警告を出していたので、特に自前propsが無意識に渡されて警告が出がちなStyled Componentsにおいては重要な機能と言えるでしょう。

emotionでカスタム属性を通す方法

ただ、当然このままだと困るケースもあるわけで、じゃあそういう場合はどうするかというと、ドキュメントに書いてあるとおり(←最初からちゃんとドキュメントを読めよ!)、 shouldForwardProp を指定して、自分のカスタム属性を通してあげましょう。

const CustomElem = styled("div", {
  // mycustomattr と children(子要素) のみ許可する
  shouldForwardProp: (props) => ["mycustomattr", "children"].includes(props)
})`
  color: red;
`

// @ts-ignore
return <CustomElem mycustomattr="customvalue">Hello</CustomElem>

ちゃんと結果のDOMに mycustomattr がいるはずです。逆に、他の属性を渡しても何もDOMに影響しないはずです。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2