$30 off During Our Annual Pro Sale. View Details »
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
3.1k
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
Atomics APIを知る / Understanding Atomics API
ssssota
1
550
なんでRustの環境構築してないのにRust製のツールが動くの? / Why Do Rust-Based Tools Run Without a Rust Environment?
ssssota
15
49k
Web技術を最大限活用してRAW画像を現像する / Developing RAW Images on the Web
ssssota
2
2.5k
漸進。
ssssota
0
3.2k
useSyncExternalStoreを使いまくる
ssssota
6
6.2k
React CompilerとFine Grained Reactivityと宣言的UIのこれから / The next chapter of declarative UI
ssssota
8
5.7k
新しいAPI createRawSnippet触ってみた / What is the createRawSnippet?
ssssota
2
250
脱法Svelte / Evasion of svelte rules
ssssota
1
270
Documentation testsの恩恵 / Documentation testing benefits
ssssota
2
1.1k
Other Decks in Programming
See All in Programming
複数人でのCLI/Infrastructure as Codeの暮らしを良くする
shmokmt
5
2.3k
【CA.ai #3】ワークフローから見直すAIエージェント — 必要な場面と“選ばない”判断
satoaoaka
0
240
手軽に積ん読を増やすには?/読みたい本と付き合うには?
o0h
PRO
1
170
AIコーディングエージェント(Gemini)
kondai24
0
210
Rediscover the Console - SymfonyCon Amsterdam 2025
chalasr
2
160
Microservices Platforms: When Team Topologies Meets Microservices Patterns
cer
PRO
1
1k
AtCoder Conference 2025「LLM時代のAHC」
imjk
2
440
Flutter On-device AI로 완성하는 오프라인 앱, 박제창 @DevFest INCHEON 2025
itsmedreamwalker
1
100
LLMで複雑な検索条件アセットから脱却する!! 生成的検索インタフェースの設計論
po3rin
2
680
ID管理機能開発の裏側 高速にSaaS連携を実現したチームのAI活用編
atzzcokek
0
220
AIコーディングエージェント(skywork)
kondai24
0
160
tparseでgo testの出力を見やすくする
utgwkk
1
210
Featured
See All Featured
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
54k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.3k
Build your cross-platform service in a week with App Engine
jlugia
234
18k
Designing for Performance
lara
610
69k
Become a Pro
speakerdeck
PRO
31
5.7k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.5k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
1
97
The Illustrated Children's Guide to Kubernetes
chrisshort
51
51k
Build The Right Thing And Hit Your Dates
maggiecrowley
38
3k
Building Applications with DynamoDB
mza
96
6.8k
Facilitating Awesome Meetings
lara
57
6.7k
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っておもしれーライブラリ。