2024.12.10
“放置系”なのにサイバー攻撃を監視・検知、「統合ログ管理ツール」とは 最先端のログ管理体制を実現する方法
React HooksとReduxとProxy(全1記事)
リンクをコピー
記事をブックマーク
Daishi Kato(@dai_shi)氏:よろしくお願いします。「React HooksとReduxとProxy」というタイトルで発表します。
自己紹介をさせていただきます。加藤大志といいます。
今、フリーランスプログラマーで、仕事募集中の状態です。最近はTwitterをがんばっていまして、TwitterとMediumとGitHubにいろいろ書いています。
React自体は「0.14」から使い始めました。最初に出てきた頃……createClassが出てきた時は、ぜんぜん魅力を感じませんでしたが、0.14からfunction componentsが使えるようになって、非常に魅力的に感じて使い始めました。
その時は「function componentsだけで書きたい」と思っていました。Reduxの相性がすごくよかったので、はじめはReduxで「もうLocal stateは一切使わないで、全部Global stateに入れてしまえ」というスタイルを採用していました。
React Hooksが出たわけですが、React Hooksはfunction componentsですべてが完結する仕組みです。もともとの経緯がそうなので、とても歓迎しています。
0.14が出たときにも「もうすぐできるよ」と言われていて、しばらく待ったらすぐにできるかなと思って、Reduxでがんばっていましたが、実際はだいぶかかりましたね。やっとReact Hooksが出てきて、晴れてfunction componentsだけで書けるようになって、うれしいかぎりです。
React Hooksが好き過ぎて、小さいライブラリをたくさん作っています。今は6個ぐらい作っていて、今日はそのうちの「react-hooks-easy-redux」というライブラリについて紹介します。
そもそもReduxとReact Reduxは分けて考えるもので、Redux自体は独立した、Reactとは関係のないライブラリになっています。実際、99行で実装できるくらい小さいです。最初は本当に小さかったなと思います。
一方で、React ReduxはReduxとつなげるバインディングライブラリになっています。これは非常に複雑というか、Reactの中でReduxを使うためにパフォーマンスチューニングされています。
ただ、そのパフォーマンスをきちんと理解して使うにはObject Identityやselectorなどの理解が必要で、初心者にはちょっと難しいなと思います。例えば、Reactが初めての人に教えるとき、そこがないと進まないのはちょっとつらいなと感じたことがありました。React Reduxのパフォーマンスのよさはあると思いますが、別の手があってもいいんじゃないかなと思っていました。
そして、React Hooksが登場してから、いろんな人がReduxの代替ライブラリのようなものを一生懸命作っています。
2つぐらいタイプがあって、1つは、Reduxを使わずにHooksだけでなんとなく似たようなことをするというものです。もう1つは、Reduxを使いつつ、React Reduxは使わずに、それに代わるバインディングをHooksで実現するというものです。私はどっちもやっていますが、今日紹介するのは後者のほうです。
ここまでが導入で、残りは、(スライドを指して)だいたいこれが一般的にどうやって実装されているかという紹介と、その問題点を示して、解決策の候補と、Proxyを使った解決策をご紹介しようと思います。
まず導入として、ReduxのStoreが普通に作られる感じをイメージしてください。stateにcounterの数字とtextの文字列があるRedux Storeを作ったとします。
これをHooksで使ったときの1つのイメージが(スライドを指して)こちら。Counterコンポーネントがあって、stateを取ってくるhookとdispatchを取ってくるhookがあって、コールバックを作って、そのstateを表示したり、そのコールバックをイベントから呼び出したりするように書きます。
countとtextが2つ、stateの中に入っているんですけど、普通に何事も考えずにやると、このコンポーネントではCounterしか使っていないにもかかわらず、state.textが変更された場合もレンダリングされてしまいます。
ちなみに、先ほどの例を実現する素朴な実装は(スライドを指して)こんな感じです。それぞれのHooksの実装……といっても1個しかないですが、こんな感じで作ります。あとでまた資料を公開するので、見ていただけたらと思います。
ただ、これは参考程度というか、実際にこのまま使うことはありません。いろんな問題点があるので、使わないです。
先ほど言いましたが、そもそも「変更検知問題」というものがあります。
Redux stateは、一般的には、アプリに大きく1個のGlobal stateを作るんですけれど、その一部の変更によって、ぜんぜん関係ないコンポーネント、stateの一部の使わないコンポーネントまでレンダリングすることは避けたい、という問題があります。
一方で、仮にすごく小さいアプリや限定的にReduxを使っている場合で、パフォーマンスがそんなに問題にならなければ、先ほどのような素朴な実装でもそこまで問題ないです。アプリの形態によると思いますけど、問題にならないこともあります。
解決法としては、selectorを指定する方法と、memoizeする方法と、auto-detectする方法があると思います。ほかにもあるかもしれませんが、今日はauto-detectを採用するかたちです。一応、ほかの方法も紹介しておこうと思います。
selectorは、いわゆるReact Reduxのconnectを使ったもので、ただそのままなんですけど、stateから部分集合を取り出すようなselectorの関数をhookに渡して、部分集合を取り出してそれを使う。この部分集合に該当しない場合はレンダリングしないという作り方をします。これが一番シンプルですね。
(スライドを指して)これはmemoizationを使ったケースです。全部取ってきてしまうけれど、変わった部分や自分が使うとわかっている部分を、input arrayで渡してメモする。それによって、実際は一瞬だけrender関数が実行されるんですけど、そこまでひどくないというか、パフォーマンスはそこそこ出ます。
これは完全ではないかもしれないです。ちょっと見にくいかなというところはありますし、あまり一般的ではなく、提案されているようなやり方ではないです。
最後のauto-detectですが、これは先ほど紹介した使い方と一緒です。stateを丸々持ってきて、stateのcounterを表示するだけのレンダリングで、解決策1でselectorを指定したものと同じような動作をしようというものです。
「そんなことができるか?」という話なんですけど、Proxyというものがあって、オブジェクトの操作をトラップして処理を行います。
これを使うと、そのstateの中のどこか一部分が読まれて……または書かれてでもいいんですけど、そこが触られたときに、触られたということを記録しておいて、あとでstateから変更されたときに「触られたところに該当するかどうか」で、レンダリングするかしないかを判断できます。
このアプローチを採用してみようということで、先ほど紹介したライブラリ「react-hooks-easy-redux」を作りました。
1個だけ、依存ライブラリになるものが入っていて、proxyequalというライブラリです。Proxy自体は、1個のオブジェクトに対して適用するんですけど、それを深いオブジェクトに対して再帰的に適用してくれるものです。(スライドを指して)実際に、これを作りました。
Proxyは一応コストがかかるので、どれぐらいコストがかかるのかなと思ってベンチマークテストをしました。と言っても、たった1個のシンプルなベンチマーク用のアプリを使って動かしているだけなので、これがすべてではないんですけど、一例としては(スライドを指して)こうなります。
スライドの左上に出ているReact Redux v5.0.7の例が評価対象で、FPSが50ぐらいです。それに対して、今回私が作ったreact-hooks-easy-reduxのv0.8.0は、FPSが8.37。実際に触ってもわかるぐらい遅くなって、パフォーマンスが出ないという問題がありました。
いろいろと調べていったところ、先ほどご紹介したproxyequalの依存ライブラリに問題があることがわかりました。そして、proxyequalの作者と一緒にそのボトルネックを解消して、新しいバージョンを作って、今は38.96ぐらいのFPSが出るようになっています。
体感でももちろんわかるんですけど、もとから比べれば断然「マシ」です。これなら利用に堪えられるかなくらいにはなっていますね。
これで終わりなんですが、興味のある方はぜひ使ってみてください。
Reduxを使って、さっきみたいに簡単に書けるのかとか、custom hooksはどんなものなのかとか、ベンチマークテストをもっとやってみたいとか、そういう方がいらしたら、ぜひ見てみてください。
以上で発表を終わります。ありがとうございました。
(会場拍手)
関連タグ:
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
2024.12.09
国内の有名ホテルでは、マグロ丼がなんと1杯「24,000円」 「良いものをより安く」を追いすぎた日本にとって値上げが重要な理由
2024.11.29
「明日までにお願いできますか?」ちょっとカチンとくる一言 頭がいい人に見える上品な言い方に変えるコツ
2024.12.09
10点満点中7点の部下に言うべきこと 部下を育成できない上司の特徴トップ5
2024.12.04
いつも遅刻や自慢話…自分勝手な人にイラっとした時の切り返し 不平等な関係を打開する「相手の期待」を裏切る技
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.12.03
職場の同僚にイライラ…ストレスを最小限に抑える方法 臨床心理士が語る、「いい人でいなきゃ」と自分を追い込むタイプへの処方箋
2024.12.06
嫌いな相手の行動が気になって仕方ない… 臨床心理士が教える、人間関係のストレスを軽くする知恵
2024.12.05
「今日こそやろう」と決めたのに…自己嫌悪でイライラする日々を変えるには
PR | 2024.12.04
攻撃者はVPNを狙っている ゼロトラストならランサムウェア攻撃を防げる理由と仕組み