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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
193Otani
July 28, 2022
Programming
140
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
Railsバージョンを4倍にした話
optim
0
350
FactoryBotをやめればRSpecは速くなるのか?
yuta_onishi_97
0
330
JAWS-UG 東京支部が始める、JAWS-UG支部コラボ / JAWS-UG lunchtime LT Collaboration
y0hgi
0
270
[ハンズオン]AIへの指示だけで「五目並べ」を作ってみよう
satoshi256kbyte
1
380
Vue Fes Japan の “作る側”に関わってみて
naokihaba
0
160
設計次第でAIコードの読む量は減らせる / designing-for-code-reading
minodriven
35
17k
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
300
dotNET_vulnclicker_intro.pdf
deka_morita
0
140
最近”作らせてる” ローカルAIアプリの話
akit37
0
470
Optunaを作ったときにやりたかったこと、その後 (2026/10/16, Optuna Meetup #3)
iwiwi
1
430
JIS keyboard support in Omarchy
lef237
0
110
SREの越境 / SRE Collaboration
y0hgi
2
310
Featured
See All Featured
KATA
mclloyd
PRO
35
16k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
520
Chasing Engaging Ingredients in Design
codingconduct
0
360
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.8k
Visualization
eitanlees
153
17k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
How STYLIGHT went responsive
nonsquared
100
6.3k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.2k
Bootstrapping a Software Product
garrettdimon
PRO
306
120k
The untapped power of vector embeddings
frankvandijk
2
1.9k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.4k
The Invisible Side of Design
smashingmag
301
52k
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とその周りについて調べた