概要
Material-UIのビルトインのアイコンを使おうと思った時に、
- 一覧がない(私が見つけられなかっただけかも知れない)
- Outlinedとか違いがわかりにくい
というつらさを感じていた中、ある日朝目覚めた時に「今日はアイコンの一覧を作る日だ」となぜか強く感じたので実際に作ってみました。作る過程でJSXについて新しく学ぶことがあったのでそれをまとめます。
できた一覧はこちらです。
ちなみに
私とReactのこれまでは、有志のReactのプロジェクトに参加するぞ!となってざっと入門を読んでいきなり書き始めたようなもの(=時間をかけて体系的に学んだわけではない)なので、もしかしたらすごい今更なことを書いているかも知れません。
importしてるアイコンの中身とは
いつもアイコンを使うときに@material-ui/icons/XXX
からimportしているので、@material-ui/icons
に行ったら全部取得できるのでは??と思いimport * as icons from '@material-ui/icons'
としてみました。すると、オブジェクト形式でアイコンの全量が取得できました。
このアイコンの中身が何を持っているかconsole.logでのぞいてみると
{
$$typeof: Symbol(react.memo)
compare: null
displayName: "WhereToVoteIcon"
muiName: "SvgIcon"
type:
$$typeof: Symbol(react.forward_ref)
render: ƒ (props, ref)
}
こんなものを持っていました。それぞれのプロパティがどんな役割を果たすのか全くわかりませんでしたが、render
っていうのを持っているのをみて、これ使えばなんとか描画できる何かなんだな〜と言うことがわかりました。(importしたモジュールなので当然なのですが)
JSXの正体とは
ということで、とりあえず特徴的な$$typeof
を調べてみると、「なぜReactのコンポーネントは$$typeofプロパティを持っているのか」という記事にぶつかりました。
ここの冒頭で一気にアイコンの描画に近づくわけなのですが、そのまま例を借りると、つまり
<marquee bgcolor="#ffa7c4">hi</marquee>
こういうJSXを書いている時、実際に行われているのは
React.createElement(
/* type */ 'marquee',
/* props */ { bgcolor: '#ffa7c4' },
/* children */ 'hi'
)
だと言うのです。
ここで、 普段Material UIのアイコンを使う時に書くのはタグ名だけなので、つまりこのimportしたものをcreateElementにぶち込めばいいと言うことだな! と思ったので先ほどconsole.log()
でのぞいた中身を渡したところ、無事描画ができました!
$$typeofとは
ここでもう目的は達成したわけですが、せっかくなので$$typeof
について知るべくもう少し読み進めてみましょう。以下要約なので詳しく知りたい方は元記事を参照してください。
- 攻撃を防ぐため、Reactはテキストをデフォルトでstringにしてescapeしている
- それだけで必ずしもインジェクション攻撃に勝てるかと言うとそうではない
- ところで、ReactのElementはデザインとしてはプレーンなオブジェクトである
- (とはいえ自分で
React.createComponent()
するとき必ずそうしろと言うことではない - object形式であることにはコンパイラの最適化などいくつかの利点がある
- だけども、もし
string
が想定されているところに、もし万が一恣意的なJSONを渡せる欠陥があったとすると、これはXSS攻撃に対する脆弱性となる - ここで
$$typeof: Symbol.for('react.element'),
が生きてくる - 万が一そう言う欠陥があったとしても、JSONに
Symbol
を入れることは不可能だからである - それを利用して、Reactは
$$typeof
がなかったり不正だったりすると解釈をやめるようになっている
以上、そうだったのか!と言うことでJSXとちょっと仲良くなれた気がしました
最後まで目を通して頂きありがとうございました