Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Preact、HooksとSignalsの両立 / Preact: Harmonizing H...
Search
TOMIKAWA Sotaro
March 28, 2025
Programming
1
2k
Preact、HooksとSignalsの両立 / Preact: Harmonizing Hooks and Signals
https://vuejs-meetup.connpass.com/event/343338/
TOMIKAWA Sotaro
March 28, 2025
Tweet
Share
More Decks by TOMIKAWA Sotaro
See All by TOMIKAWA Sotaro
useSyncExternalStoreを使いまくる
ssssota
6
5.4k
React CompilerとFine Grained Reactivityと宣言的UIのこれから / The next chapter of declarative UI
ssssota
7
5k
新しいAPI createRawSnippet触ってみた / What is the createRawSnippet?
ssssota
2
160
脱法Svelte / Evasion of svelte rules
ssssota
1
200
Documentation testsの恩恵 / Documentation testing benefits
ssssota
2
990
TypeScriptとDocumentaion tests / Documentation tests with TypeScript
ssssota
8
3.9k
Svelteでライブラリを作る / Make your library with Svelte
ssssota
0
150
現代のReactivityとSvelteの魔法
ssssota
0
2.1k
型付きdotenv
ssssota
0
340
Other Decks in Programming
See All in Programming
Vibe Coding の話をしよう
schroneko
14
3.8k
KANNA Android の技術的課題と取り組み
watabee
1
510
Instrumentsを使用した アプリのパフォーマンス向上方法
hinakko
0
250
Beyond_the_Prompt__Evaluating__Testing__and_Securing_LLM_Applications.pdf
meteatamel
0
110
バイラテラルアップサンプリング
fadis
3
540
“技術カンファレンスで何か変わる?” ──RubyKaigi後の自分とチームを振り返る
ssagara00
0
110
Golangci-lint v2爆誕: 君たちはどうすべきか
logica0419
1
260
個人開発の学生アプリが企業譲渡されるまで
akidon0000
2
1.2k
파급효과: From AI to Android Development
l2hyunwoo
0
160
VitestのIn-Source Testingが便利
taro28
9
2.5k
eBPF超入門「o11yに使える」とは (20250424_eBPF_o11y)
thousanda
1
120
プロフェッショナルとしての成長「問題の深掘り」が導く真のスキルアップ / issue-analysis-and-skill-up
minodriven
8
2k
Featured
See All Featured
Side Projects
sachag
453
42k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
13
840
Building an army of robots
kneath
305
45k
How to Ace a Technical Interview
jacobian
276
23k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
49k
Code Reviewing Like a Champion
maltzj
523
40k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
331
21k
RailsConf 2023
tenderlove
30
1.1k
Facilitating Awesome Meetings
lara
54
6.4k
The Art of Programming - Codeland 2020
erikaheidi
54
13k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
227
22k
Transcript
Preact、 HooksとSignalsの両立 Preact: Harmonizing Hooks and Signals #v_tokyo22 / ssssota
自己紹介 ssssota { "twitter": "@ssssotaro", "github": "ssssota", "bsky": "@ssssota.bsky.social" }
株式会社ZOZO フロントエンドテックリード 仕事でReact、 趣味でSvelteやPreactを主に触っている。
Preact ? > Fast 3kB alternative to React with the
same modern API > Preact(プリアクト)はDOM上に薄い仮想DOMによる抽象化を提供します。 https://preactjs.com/ React互換を謳う軽量な仮想DOMライブラリ。 Reactの進化についていく気がないので互換性については...。 DenoがFreshに採用するなど、死んではいない。 Majorバージョンの更新こそないが、Minorバージョンの更新はある。
Hooks ? いわゆるReact Hooks。 useState, useEffect, useRef, etc… 関数コンポーネントにリアクティビティ(状態や副作用)を導入する道具。 登場当時はクラスコンポーネントが主流だった。しかしクラスインスタンス自体が状態
を持つことで、ロジックの分離が困難になっていた。 フックによりロジックは再利用性が向上。コンポーネントとはより疎な関係に。 Preactでは、Reactの一部フックが同様に利用できる。
Signals ? preact本体とは別パッケージ(@preact/signals)として提供されていつつも、 高度に統合されたSignals実装。 signal, computed, effectなど基本的なAPIから、 関数コンポーネント/カスタムフックから利用するための useSignal, useComputed,
useSignalEffectなどが提供されている。 限定的ではあるもののFine-grained Reactivityが実現されている。
options Preactにはoptionsというオブジェクトがexportされている。 このオブジェクトにはPreactが内部的に利用するライフサイクルフックが登録され、 上書きすることにより各種挙動の拡張を可能にしている。 @preact/signalsはoptionsのライフサイクルフックを上書きすることで SignalをPreactに統合している。
Reactivity with Hooks(VDOM) Code (Preact / React) function Counter() {
const [count, setCount] = useState(0); const increment = () => setCount(p => p + 1); return ( <div> {count} <button onClick={increment}>+1</button> </div> ); }
Reactivity with Hooks(VDOM) VDOM UI 0 [+1] Code function Counter()
{ const [count, setCount] = useState(0); const increment = () => setCount(p => p + 1); return ( <div> {count} <button onClick={increment}>+1</button> </div> ); }
Reactivity with Hooks(VDOM) VDOM (ボタン押下でsetCountが呼ばれる) UI 0 [+1] Code function
Counter() { const [count, setCount] = useState(0); const increment = () => setCount(p => p + 1); return ( <div> {count} <button onClick={increment}>+1</button> </div> ); }
Reactivity with Hooks(VDOM) VDOM (VDOMを作り直して比較) UI 0 [+1] Code function
Counter() { const [count, setCount] = useState(0); const increment = () => setCount(p => p + 1); return ( <div> {count} <button onClick={increment}>+1</button> </div> ); }
Reactivity with Hooks(VDOM) VDOM UI (差分を適用) 1 [+1] Code function
Counter() { const [count, setCount] = useState(0); const increment = () => setCount(p => p + 1); return ( <div> {count} <button onClick={increment}>+1</button> </div> ); }
Reactivity with Signals(VDOM) Code (Preact) function Counter() { const count
= useSignal(0); const increment = () => { count.value += 1; }; return ( <div> {count.value} <button onClick={increment}>+1</button> </div> ); }
Reactivity with Signals(VDOM) VDOM UI 0 [+1] Code function Counter()
{ const count = useSignal(0); const increment = () => { count.value += 1; }; return ( <div> {count.value} <button onClick={increment}>+1</button> </div> ); }
Reactivity with Signals(VDOM) VDOM (ボタン押下でcountがインクリメント) UI 0 [+1] Code function
Counter() { const count = useSignal(0); const increment = () => { count.value += 1; }; return ( <div> {count.value} <button onClick={increment}>+1</button> </div> ); }
Reactivity with Signals(VDOM) VDOM (VDOMを作り直して比較) UI 0 [+1] Code function
Counter() { const count = useSignal(0); const increment = () => { count.value += 1; }; return ( <div> {count.value} <button onClick={increment}>+1</button> </div> ); }
Reactivity with Signals(VDOM) VDOM UI (差分を適用) 1 [+1] Code function
Counter() { const count = useSignal(0); const increment = () => { count.value += 1; }; return ( <div> {count.value} <button onClick={increment}>+1</button> </div> ); }
Reactivity 基本方針は、「Signalが更新されたらそのコンポーネントを再レンダリング」。 あくまでも仮想DOMベースのリアクティブシステムなので、 1. 状態を元に仮想DOMの構築 2. 仮想DOMツリーを比較 (diffing / reconciliation) 3.
実DOMへの反映 (render / commit) が基本。Signalsを使っても同じ規則に従うことで共存できる。 PreactのSignalsは限定的なFine-grained Reactivityが実現されている。 仮想DOMの構築やツリーの比較を行わずにDOMを更新できるので速い。
Fine-grained Reactivity with Signals(VDOM) Code (Preact) function Counter() { const
count = useSignal(0); const increment = () => { count.value += 1; }; return ( <div> {count /* UPDATED! (before: count.value) */} <button onClick={increment}>+1</button> </div> ); }
Fine-grained Reactivity with Signals(VDOM) VDOM UI 0 [+1] Code function
Counter() { const count = useSignal(0); const increment = () => { count.value += 1; }; return ( <div> {count} <button onClick={increment}>+1</button> </div> ); }
Fine-grained Reactivity with Signals(VDOM) VDOM (ボタン押下でcountがインクリメント) UI 0 [+1] Code
function Counter() { const count = useSignal(0); const increment = () => { count.value += 1; }; return ( <div> {count} <button onClick={increment}>+1</button> </div> ); }
Fine-grained Reactivity with Signals(VDOM) VDOM (count使用箇所更新) UI (count使用箇所更新) 1 [+1]
Code function Counter() { const count = useSignal(0); const increment = () => { count.value += 1; }; return ( <div> {count} <button onClick={increment}>+1</button> </div> ); }
None
PreactのSignalは通常 .value プロパティによって値を取得・更新できる。 しかし、JSXの各値にSignalをそのまま設定できる。 その部分はFine-grained Reactivityが適用される。 <p>{someSignal /* someSignal.value ではなくていい
*/}</p> <input value={someSignal /* someSignal.value ではなくていい */} onChange={(e) => (someSignal.value = e.currentTarget.value)} /> 限定的...? Fine-grained Reactivity
Limitation of Preact signals JSX内で .value をつけなければFine-grained Reactivityを適用できるが、常 にFine-grained Reactivityが適用できるわけではない。
例えば、 1. {themeSignal.value === 'light' ? <Light /> : <Dark />} 2. {listSignal.value.map(item => <Item item={item} />)} 条件分岐と反復に関してはFine-grained Reactivityが適用できない =変化時、仮想DOMの再構築が必須 (SolidJSでも <For/> や <Switch/> などで同様の制約を回避)
const countGlobalSignal = signal(0); function Counter() { const countLocalSignal =
useSignal(0); const [count, setCount] = useState(0); return ...; } もちろん同時に使える。 とはいえ、 useSignal と useState を乱用すると治安が崩壊する。 「useSignal 禁止」など、プロジェクト毎にルールを決めてご利用は計画的に。 Hooks and Signals
まとめ PreactにはSignalsがある。 Preact本体とは別パッケージながらoptionsにより統合されている。 Signalsは分岐と反復で制約を受けるもののFine-grained Reactivityを実現、 パフォーマンスに寄与する。 PreactにはHooksもあり、共存できる。状況に応じ使い分けよう。 Signalsのパフォーマンスは良いが、PreactではHooksを圧倒するものではない。 JSXだし、Reactより軽量だし、それなりに速いし、Signalsあるし、 Preactっておもしれーライブラリ。