Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
React Hooksの実装を探検してみる / Explore the React Hooks...
Search
193Otani
July 28, 2022
Programming
130
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
React Hooksの実装を探検してみる / Explore the React Hooks implementation
193Otani
July 28, 2022
Other Decks in Programming
See All in Programming
WebRTC映像をAirPlayに対応させる挑戦.pdf
monolithic_adam
0
290
一人だけ、Kiroが静止する日
hideg
0
120
wkhtmltopdfの次どうするか問題2026
willnet
2
1.5k
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
150
AIは賢い。でも実行環境は? CLIおじさんがAI時代に伝えたいこと ~ CLIおじさんがAI時代に伝えたいこと ~
curekoshimizu
1
250
AgentCore CLI で進化した AWS での AI エージェントの作り方 : 必要な機能を必要な時に
icoxfog417
PRO
3
350
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
9
4.8k
WebAssembly in Android Apps 〜 WASMはJNIの夢を見るか
keiji
1
110
Streamlitで実現する自然言語データアプリ開発
ayumu_yamaguchi
1
290
すこし踏み込む CancellationToken
htkym
2
560
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
260
Vibes Containers 〜AIで変わるコンテナ設計と運用〜
tkikuc
3
550
Featured
See All Featured
Why Our Code Smells
bkeepers
PRO
340
58k
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
290
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
380
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
680
For a Future-Friendly Web
brad_frost
183
10k
Building AI with AI
inesmontani
PRO
1
1.2k
Navigating Team Friction
lara
192
16k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
2
2.1k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
46k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.4k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
4
1.2k
Transcript
React Hooksの実装を探検してみる 株式会社カオナビ プロダクト本部 サービス開発部 Data Frontier グループ 大谷 育未
自己紹介 # 経歴 • 2020年4月にカオナビに新卒入社 • 2年目からフロントエンドエンジニアとして本格的にスタート • 現在は機能拡充を中心としたチームにて活動中 •
趣味はダーツ、ゲーム、モータースポーツ ◦ 今年はF1がアツいです
目指すこと/目指さないこと # 目指すこと • Hooksが呼び出されたときReactがなにをしているのかをざっくり理解する • 調査の過程で出てきたReact内部の構造、キーワードを知ってもらう # 目指さないこと •
React / React Hooksの動作原理を完璧に理解する • 登場するキーワードについて完全に理解する
Reactとは? • .FUB چ'BDFCPPL ͱίϛϡχςΟʹΑͬͯ։ൃ͞Ε͍ͯΔɺ6*ߏஙͷͨΊ ͷKBWBTDSJQUϥΠϒϥϦ (JUIVC GBDFCPPLSFBDU •
ҎԼͷͭΛίϯηϓτͱͯ͠։ൃ͞Ε͍ͯΔ ◦ એݴతͳ7JFX ◦ ίϯϙʔωϯτϕʔε ◦ Ұֶश͢ΕɺͲ͜Ͱ͑Δ • 8FCϒϥβ͚ͷ6*։ൃʹՃ͑ɺ3FBDU/BUJWFΛ༻͍ͨϞόΠϧΞϓϦ ͷ։ൃʹར༻Ͱ͖Δ
React Hooksとは? • React 16.8から追加されたReactの新機能群 • 関数コンポーネント内でReactのstateやライフサイクルメソッドを使用する ことができる(クラスコンポーネント内では機能しない) • ビルトインですぐに利用できるHooksが用意されている
◦ useState, useEffect, useMemo etc…
今回のターゲットはuseEffect
useEffectとは? • 関数コンポーネント内で副作用を実行することができる ◦ 副作用とは? - ある処理を実行した結果他の処理に対して影響を伴うようなもの ◦ stateの値を更新する、APIの値を取得するなど •
useEffectに渡された副作用関数は画面のレンダリング後に発火される • クラスコンポーネントにおける以下のライフサイクルメソッドの代替機能 ◦ componentDidMount, componentDidUpdate, componentWillUnmount
useEffectの本体 • react/src/ReactHooks.js • ReactCurrentDispatcher.current.useEffect(create, deps)を返している ◦ create -> useEffectで実行させたい副作用関数
◦ deps -> 副作用関数が依存している変数の配列 // @flow export function useEffect( create: () => (() => void) | void, deps: Array<mixed> | void | null, ): void { const dispatcher = resolveDispatcher(); return dispatcher.useEffect(create, deps); } // @flow import ReactCurrentDispatcher from './ReactCurrentDispatcher'; function resolveDispatcher() { const dispatcher = ReactCurrentDispatcher.current; … // コメント省略 return ((dispatcher: any): Dispatcher); }
ReactCurrentDispatcherを見る • ReactCurrentDispatcher.js • currentの中身空っぽいんだけど? ◦ Dispatcher型がセットされるようだが...? ◦ react-reconcilerってなんだ? //
@flow import type {Dispatcher} from 'react- reconciler/src/ReactInternalTypes'; const ReactCurrentDispatcher = { /** * @internal * @type {ReactComponent} */ current: (null: null | Dispatcher), }; export default ReactCurrentDispatcher;
React-Reconcilerってなに? • Fiberという単位でコンポーネントの状態や更新情報を管理している ◦ Fiberは一つのコンポーネントに対して基本的に1:1で存在する ◦ FiberのTreeを構成し、さらに変更前と変更後の二つのTreeを比較することで、更 新が必要な差分の検出を行っている(Reconciliation) • Reconcilerはこの差分検出処理群
• コアロジックを共有することで、Webアプリやネイティブアプリにおける動 作の一貫性を保っている ◦ ブラウザ開発開発: React + React DOM ◦ モバイル向け開発: React + React Native
ReactにおけるFiberとは? • コンポーネントの状態や仮想DOM情報をもつオブジェクト • コンポーネントに対してFiberは必ず1つは存在している • ReactはFiberを連結リストとして持つことで、コンポーネントごとに状態や 更新管理を行うことができる
Reconcilerが行う差分検出のイメージ Reconciliation Current WorkInProgress Time 1 Time 2
結局、ReactCurrentDispatcher.currentの中身は? • renderWithHooks - ReactFiberHooks.new.js: L.373 • currentの中身はHooksDispatcherOnMount or HooksDispatcherOnUpdate
◦ 各Hookに対応した関数を持つオブジェクト ◦ OnMount: L.2420 ◦ OnUpdate: L. 2427 // ReactFiberHooks.new.js - L.373 … if (__DEV__) { ... } else { ReactCurrentDispatcher.current = current === null || current.memoizedState === null ? HooksDispatcherOnMount : HooksDispatcherOnUpdate; } …
HooksDispatcherOnMount • 各Hookに対応する初期化関数をもっている • OnUpdateの場合は更新関数が割り当てら れている ◦ useEffect: updateEffect const
HooksDispatcherOnMount: Dispatcher = { readContext, useCallback: mountCallback, useContext: readContext, useEffect: mountEffect, useImperativeHandle: mountImperativeHandle, …, useId: mountId, unstable_isNewReconciler: enableNewReconciler, };
mountEffect(...) • 特別な処理はなさそう • mounEffectImplに渡しているフラグが気になる // ReactFiberHooks.new.jp - L.1701 function
mountEffect( create: () => (() => void) | void, deps: Array<mixed> | void | null, ): void { if ( __DEV__ && … ) { return mountEffectImpl(...); } else { return mountEffectImpl( PassiveEffect | PassiveStaticEffect, HookPassive, create, deps, ); } }
mountEffectImpl(...) • mountWorkInProgressHook(...) - L.635 ◦ Effect Hookの状態管理ツリーに現在の状態が保存されたノ ードを追加 ◦
上記ノードが持っている情報ごと • pushEffect(...) - L. 1543 ◦ 現在のeffectの状態を保存したEffectノードを作成 し、Fiberが持っている更新キューに追加 ◦ 保存される情報には依存配列の状態を含む // ReactFiberHooks.new.js - L. 1662 function mountEffectImpl(fiberFlags, hookFlags, create, deps): void { const hook = mountWorkInProgressHook(); const nextDeps = deps === undefined ? null : deps; currentlyRenderingFiber.flags |= fiberFlags; hook.memoizedState = pushEffect( HookHasEffect | hookFlags, create, undefined, nextDeps, ); }
useEffectの初回呼び出し 1. useEffect(...)が呼び出されると最終的にmountEffectImpl(...)が呼ばれる 2. 新しいHookが実行されること、そのHookがEffect Hookによる更新であるこ とがFiberに伝えられる
2回目以降の動きはどうなるのか? • useEffectは基本的に毎レンダリング呼び出される • useEffectは引数として依存する変数の配列を渡すことができる • 依存配列の中身が変わらない場合はuseEffectの処理は実行されない useEffect(() => {
console.log(effectVal); },[effectVal]);
updateEffectImplに秘密が... • 入力される依存配列が過去に使用したものと一致するかチェックしている • 一致した場合、flagsの更新をしていない = useEffectの動作と一致している // L. 1674
const prevDeps = prevEffect.deps; if (areHookInputsEqual(nextDeps, prevDeps)) { hook.memoizedState = pushEffect(hookFlags, create, destroy, nextDeps); return; } } } currentlyRenderingFiber.flags |= fiberFlags; // 副作用を適用するフラグを立てる
useEffectの実装を追ってみて • എܠʹ͋Δ࣮ͷҙਤ։ൃνʔϜͷߟ͑ํʹ;ΕΔ͜ͱ͕Ͱ͖ͨ • ReconcilerɺFiberͷಋೖཧ༝ͳͲ • ίʔυΛඈͼඈͼͰ͏ඞཁ͕͋Δ+FiberΛར༻ͨ͠ཧํ๏ʹෆ׳ΕͰί ʔυΛͬͯཧղ͢ΔͷΘΓͱେม • React
Hooksଞʹ࣮͞Ε͍ͯΔͷͰɺڵຯ͕͋ΔํͬͯΈͯʁ ◦ ࣗuseEffectͷ࣮͏ͷͰർΕ·ͨ͠...
参考 • React-Fiber-Architecture • Reconciliation - React • An Introduction
to React Fiber - The Algorithm Behind React • React Fiberとその周りについて調べた