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
ドメイン駆動設計とXPで支える子どもの未来 / Domain-Driven Design and XP Supporting Children's Future
nrslib
0
290
KawaiiLT 登壇資料 キャリアとモチベーション
hiiragi
0
160
Storybookの情報をMCPサーバー化する
shota_tech
3
1.2k
SwiftDataのカスタムデータストアを試してみた
1mash0
0
150
generative-ai-use-cases(GenU)の推しポイント ~2025年4月版~
hideg
1
400
設計の本質:コード、システム、そして組織へ / The Essence of Design: To Code, Systems, and Organizations
nrslib
10
3.8k
In geheimer Mission: AI Agents entwickeln
joergneumann
0
120
GitHub Copilot for Azureを使い倒したい
ymd65536
1
330
Rubyの!メソッドをちゃんと理解する
alstrocrack
1
310
バイラテラルアップサンプリング
fadis
3
550
AWS Summit Hong Kong 2025: Reinventing Programming - How AI Transforms Our Enterprise Coding Approach
dwchiang
0
140
iOSアプリで測る!名古屋駅までの 方向と距離
ryunakayama
0
160
Featured
See All Featured
Building a Scalable Design System with Sketch
lauravandoore
462
33k
Designing for humans not robots
tammielis
253
25k
How STYLIGHT went responsive
nonsquared
100
5.5k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
10
800
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3.2k
Code Review Best Practice
trishagee
68
18k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
251
21k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.6k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.8k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
24
2.7k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
49k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
331
21k
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っておもしれーライブラリ。