2019/06/24
Material-UIのビルトインのアイコンを使おうと思った時に、
というつらさを感じていた中、ある日朝目覚めた時に「今日はアイコンの一覧を作る日だ」となぜか強く感じたので実際に作ってみました。作る過程でJSXについて新しく学ぶことがあったのでそれをまとめます。
できた一覧はこちらです。
私とReactのこれまでは、有志のReactのプロジェクトに参加するぞ!となってざっと入門を読んでいきなり書き始めたようなもの(=時間をかけて体系的に学んだわけではない)なので、もしかしたらすごい今更なことを書いているかも知れません。
いつもアイコンを使うときに@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したモジュールなので当然なのですが)
ということで、とりあえず特徴的な$$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
について知るべくもう少し読み進めてみましょう。以下要約なので詳しく知りたい方は元記事を参照してください。
React.createComponent()
するとき必ずそうしろと言うことではないstring
が想定されているところに、もし万が一恣意的なJSONを渡せる欠陥があったとすると、これはXSS攻撃に対する脆弱性となる$$typeof: Symbol.for('react.element'),
が生きてくるSymbol
を入れることは不可能だからである$$typeof
がなかったり不正だったりすると解釈をやめるようになっている以上、そうだったのか!と言うことでJSXとちょっと仲良くなれた気がしました
最後まで目を通して頂きありがとうございました