styled-componentsでラップした複数の子要素に同じpropsを同時に渡す
タイトルの通りです。あるコンポーネント内で配下にある全ての子要素(styled-componentsでラップされたものであるとします)に共通したpropsを渡す場合のやり方の話です。愚直に書いていたらキリがなく最悪なコードが出来上がります。
結論
styled-components/ThemeContext
を使おう。
import { ThemeContext } from 'styled-components'
具体例
まずこんな感じの複雑なコンポーネント Component
が存在しているとします。多くのコンポーネントやDOMを内包していますが、それらは全てstyled-componentsでラップされています。
const A = styled.div` /* ... */ ${props => props.value} /* ... */ ` const B = styled.div` /* ... */ ${props => props.value} /* ... */ ` const C = styled.div` /* ... */ ${props => props.value} /* ... */ ` // ... const Z = styled.div` /* ... */ ${props => props.value} /* ... */ ` const Component = () => { return ( <Container> <A /> <B /> <C /> {/* ... */} <Z /> </Container> ) }
ここで、全ての(あるいは殆どの)内包したコンポーネントで value
という共通した値を使いまわしたいとします。(この value
は useContext
などで更に上層から受け取ったものとします)
そんな時に、こんなこと↓なんてやていられません。
const Component = () => { return ( <Container> <A value={value} /> <B value={value} /> <C value={value} /> {/* ... */} <Z value={value} /> </Container> ) }
こういうときは ThemeContext
を使いましょう、一発で解決します。
const Component = () => { return ( <ThemeContext.Provider value={/* 任意の値 */}> <Container> <A /> <B /> <C /> {/* ... */} <Z /> </Container> </ThemeContext.Provider> ) }
ただし、注意点として呼び出す際のpropsのプロパティがtheme
になるので、既に違うプロパティで定義してる場合は修正しましょう。
- ${props => props.value} + ${props => props.theme}
また当然ではありますがtheme
にオブジェクトを渡すことでpropsを一層ラップした状態でこれまで通りに値を扱えます。
interface Attrs { // 渡したいpropsの型定義 } const A = styled.div` /* ... */ ${({ theme: props }: { theme: Attrs }) => props.aaa} ${({ theme: props }: { theme: Attrs }) => props.bbb} ${({ theme: props }: { theme: Attrs }) => props.ccc} /* ... */ ` const Component = () => { const attrs: Attrs = { /* ... */ } return ( <ThemeContext.Provider value={attrs}> <Container> <A /> <B /> <C /> ... <Z /> </Container> </ThemeContext.Provider> ) }
以上です。
GitHubの言語比率計算
知ってましたか?GitHubには、Repositoryごとに使用されている言語の比率を表示(計算)する素晴らしい機能があります。こんな具合に。
実はこの比率と言語は偽造できるんです。
事の発端
まず僕のツイートを見てください。ついでにフォローもしてください。
JSの占有率が嫌過ぎる pic.twitter.com/mD91kKtFQ9
— no monad (@jpnykw) April 20, 2020
これはRust(WebAssembly)とReact+TSで開発しているインタプリタのRepositoryなのですが、メインで使用していないJavaScriptの割合が「一番多い」という由々しき事態がありました。原因はWebAssemblyが吐き出してるjsがminifyされていない(出来ない)ことが原因でした。
これはかなり嫌です、JavaScriptがではなく(ほんまか?)メインで使用していな言語がラベル付されて主張されているのが個人的に嫌だったんです。
出会い
この事があまりに嫌だったのでもう一回、同じようなツイートをしてしまいました。
好みの問題ですが,RustとTS主体で書いてるのにWasmとReact使ってるから「JSが一番書いてあるで!笑笑笑」って表示されるの本当に嫌すぎる pic.twitter.com/rJkoy3zaWk
— no monad (@jpnykw) April 22, 2020
するとディレクトリ単位でignoreできる、というリプをもらいました。ちなみにgitignoreと勘違いしてますがgitattirbutesというファイルのことらしいです。
gitignoreではなくこのへんですねhttps://t.co/GEgIb7aPSr
— ぽんこつ (@ponkotuy) April 22, 2020
分からんそうならもうちょい詳しく解説しますが
linguist
ここに来てついにGitHubの言語比率計算はlinguistというツールが使われていることが判明しました。更には、configファイルを追加することで、あれこれ(例えば特定のディレクトリ以下のファイルを言語比率計算から除外するなど)出来ることが判明しました。
such as JavaScript libraries, into your git repo is a common practice, but this often inflates your project's language stats and may even cause your project to be labeled as another language.
あまりに感動したので、座右の銘にしました。WasmによってトランスパイルされたJSを除外することは、まさにピッタリの用途です。
解決
というわけでやっちゃいました。こんな簡単なことだったとは。これにて無事、でかいケツゾロリしました。めでたしめでたし。
ウオー、本当に消えた… pic.twitter.com/aUuBfBm9kO
— no monad (@jpnykw) April 22, 2020
2020年 PIXIV TECH FES に参加した
2020年2月17日に開催された PIXIV TEC FES という最高なイベントに参加してきました.
このイベントは完全招待制で, Pixivの社員の方に招待されないと参加できないようです. 僕の場合は未踏Jrで開発していたプロジェクトの関係上, シェーダー界隈の方々と繋がりがあったので, FMS_Cat*1さんに招待していただきました. (お声掛けいただきありがとうございました!)
内容が変わった
実は20:00から開催されるAFTER PARTY / LIVE PERFORMANCEがコロナウイルスの影響で中止になってしまいました. AFTER PARTYからが"""本番"""らしく, 僕も楽しみにしていたので残念でした.
#PIXIVTECHFES オワ〜 pic.twitter.com/exVyfP2Y1I
— インターネッ魚 (@jpnykw) February 17, 2020
しかし, その代わりに開場から開始までの1時間の間にDJ/VJパフォーマンスが開催されていました. これがその時の様子です. DJ/VJを生で見て滅茶苦茶感動しました. Live Codingってこんなに盛り上がるんだ. ヤバ太郎 (ボキャ貧).
始まりの時
17時ごろになるとパフォーマンスが終わって照明が落とされて画面全部にPIXIV TECH FES の文字が. いよいよ始まりを感じてドキドキが増してきました.
すると突然「「エモーーーーッショナル・スーパー・映像・オブ・エモい映像・ハイパーウルトラエモ映像」」が流れ始めました.
映像ガチのガチで最高のヤバでしたッ🔥🔥🔥 こんなテックフェス見た事なかった……………………………… ありがとうございました #PIXIVTECHFES pic.twitter.com/8tFsbqiZpE
— インターネッ魚 (@jpnykw) February 17, 2020
ライブ会場での開催だったことも有り, 音圧と映像が語感を支配してきました. テックイベントでこれはアツすぎる. ヤバいわよ! ということで動画最後にも写ってますがPixivのCTOの方の登場です.
Keynote Session
Keynote Sessionでは会社の取り組んでいる業務的な内容から技術的な内容までを社員の方々の発表形式で聞きました. Pixivの展開するサービスの紹介から, 規模など会社の概要から, Webエンジニアの方によるUI大改造の歴史のお話, App開発をするお話, データ駆動のお話, 基盤であるデータを良い感じに扱い監視するお話, 認証基盤のセキュリティ担保のお話などがありました. めちゃくちゃ為になります.
休憩
2時間にも及ぶKeynote Sessionも終わり, 休憩時間になりました. たまたまイベントにツイッタ上だけで知り合ってた方がいたのでエンカさせてもらい休憩中はお話してました.
休憩明け
小峠が登場しました. ガチで笑った.
LTバトル
最後のショートセッションは†新宿BLAZE LT BATTLE†という~潰し~戦い合いの激アツLT大会でした. 個人的に楽しみだったyui540*2さんのお話を聞けて満足でした. CSSは無料版After Effects.
最後に
冒頭でも書きましたが最高のイベントでした. 来年も開催予定らしいので, ぜひ参加したいですね. AFTER PARTY参加したい. 本当に楽しかったですありがとうございました
x86の除算命令
x86の四則演算を行う命令は add, sub, imul, idiv の4種類ある (左から, 加算, 減算, 乗算, 除算).
ここで左3つの命令は一般的な命令と同様に, 以下のBNFを満たす.
<instruction> ::= <register> "," (<register> | <value>)
しかし idiv だけ実装が特殊で, このようなことができない.
では, 具体的に を計算する方法について書く.
x86でFibonacci
最近, Cコンパイラの自作を始めました. そこでサポートしてるアセンブリがx86-64なので, アセンブリを理解する必要がりました. 折角なので, アセンブリを直接書いてfibonacciを作ってみようと思います.
雑設計
一応関数を分離して記述します.
.intel_syntax noprefix .global main, fib main: ... fib: ...
実装
愚直に実装します. 条件分岐と再帰を書きます. ediレジスタの値を計算します. 引数をstackに詰んで引っ張り, cmpの演算結果に応じてL1, L2にjumpさせればOKです.
.intel_syntax noprefix .global main, fib main: push rbp mov rbp, rsp mov edi, 10 # index call fib pop rbp ret fib: push rbp mov rbp, rsp push rbx sub rsp, 24 mov DWORD PTR [rbp-20], edi cmp DWORD PTR [rbp-20], 1 jg .L1 mov eax, 1 jmp .L2 .L1: mov eax, [rbp-20] sub eax, 1 mov edi, eax call fib mov ebx, eax mov eax, DWORD PTR [rbp-20] sub eax, 2 mov edi, eax call fib add eax, ebx .L2: add rsp, 24 pop rbx pop rbp ret
書けました.
index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | ... |
---|---|---|---|---|---|---|---|---|---|---|---|---|
value | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 | 55 | 89 | ... |
0-indexedで考えると, 実行結果が89になっていれば良いですね. では, Linux環境*1で, gccを使ってアセンブリをコンパイルして動かしてみます.
無事に出力されました 🎉
Rustの所有権について
今回はRustの借用/参照と所有権について雑に書きなぐる.
所有権とは
所有権はRustに導入されているゼロコスト抽象化*1の例の一つ. 具体的な例を上げると, 変数が非primitiveな型*2である場合に, 以下のような問題に直面する.
fn some(x: Vec<i8>) { // TODO: } fn main() { let x = vec![2]; some(x); println!("{:?}", x); }
この処理を実行してみる. 内容は順にxにVectorを代入して, xの中身をprintlnで表示している. someの中身は重要ではないので無視する. 実行してみると次のようなエラーが発生する.
borrow of moved value: `x`
意訳するとxが移動された後に借用された という意味になる. 実はこの移動されたというのは, 所有権が移動したという意味だ. xの所有権はmain関数のスコープにあった訳だが, some(x) を呼び出した時点で所有権がsomeに移動する. つまり, それ以降からxを参照しようとすると, 所有権がないのでエラーになる.
参照と借用
これを回避するためにはxの所有権を渡すのではなく, xを借用させれば良い.
fn some(x: &Vec<i8>) { // TODO: } fn main() { let x = vec![2]; some(&x); println!("{:?}", x); }
注意してほしいのが, some関数が引数で受け取る値はVector
Mutable参照
&mut T を用いることでMutable参照を実現する. この実装によってリソースの変更が可能で, 副作用を持たせることが出来る.
fn main() { let mut x = 2; { let y = &mut x; *y = 6; } println!("{}", x); }
外側のスコープで宣言したxを &mut 参照を用いてyに引き渡している. アスタリスクを引き渡したyに追加することで, 参照内容であるxにアクセスすることが出来る. 即ちxの値を書き換えることが出来る.