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
Shift-from-React-to-Vue
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Moriyama Nagi
November 01, 2024
Technology
5.4k
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Shift-from-React-to-Vue
Moriyama Nagi
November 01, 2024
More Decks by Moriyama Nagi
See All by Moriyama Nagi
AIの非決定性を吸収する設計: youtrust_09_19
calm1205
1
530
Other Decks in Technology
See All in Technology
GoにおけるFFIのこれまでとこれから
goccy
5
2.5k
AIに丸投げしないトイル削減 / Eliminating Toil Without Leaving It All to AI
kohbis
4
1.1k
なぜSRE・セキュリティは評価されないのか?守りの組織を事業成長エンジンに変えた実践
cscengineer
PRO
3
2.5k
家のリアーキテクト・リファクタリング
suguruooki
0
110
Sigmaで作る業務アプリ
kazushiro_honma
0
120
From Vanilla Kubernetes to a Batteries-Included Platform: Developer Experience at 1,300+ Clusters
yosshi_
0
680
GoCon2026 - Open Source, Open World
sanposhiho
4
3.2k
synctest時代のhttptest Go 1.27で変わるHTTPサーバテストの裏側 / go conference2026 synctest and httptest
budougumi0617
1
2.6k
2026_devsumi_ozono.pdf
o3
2
400
ペアプロの価値はコードを書くことだけじゃない
codmoninc
PRO
0
180
作品が生態系になった ─ Mini Tokyo 3D から世界へ
nagix
0
150
全員がプロダクトへ向き合う組織を持続成長させるために——組織づくりのフライホイールと4象限 / The Flywheel Model and Four Quadrants for Organizational Design
hiro_torii
4
980
Featured
See All Featured
Into the Great Unknown - MozCon
thekraken
41
2.7k
GitHub's CSS Performance
jonrohan
1033
470k
The Spectacular Lies of Maps
axbom
PRO
1
990
Everyday Curiosity
cassininazir
0
310
Amusing Abliteration
ianozsvald
1
290
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
500
The World Runs on Bad Software
bkeepers
PRO
72
12k
Crafting Experiences
bethany
1
320
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.8k
Prompt Engineering for Job Search
mfonobong
0
450
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
2
3.8k
Tell your own story through comics
letsgokoyo
1
1.1k
Transcript
©MNTSQ, Ltd. 2024/11/01 ReactからVueへの転向: 思考の変化とアプローチの違い 森山 凪
©MNTSQ, Ltd. 2 自己紹介
©MNTSQ, Ltd. 3 3年 1年 3ヶ月(趣味) 森山 凪 モリヤマ ナギ
MNTSQ株式会社 フロントエンド 4年目
©MNTSQ, Ltd. 4 過去やってきたこと
©MNTSQ, Ltd. 5 前職はHR領域のSaaSをマイクロサービスアーキテクチャで開発 自己紹介 New HR SaaS Fix
©MNTSQ, Ltd. 6 新サービスの開発方針 自己紹介 GraphQLからTypeScriptの型を自動生成 Storybook x ChromaticでのUIの差分検知 Gherkin記法でユースケースをGit管理
Cypress x CucumberでE2E API、UI、ユースケース 変われば悲鳴をあげるFE
©MNTSQ, Ltd. 7 マイクロサービスそれぞれを見てみると、、、 自己紹介 HR SaaS あれ、、 各サービスで微妙にデザインに違うな
©MNTSQ, Ltd. 8 自己紹介 HR SaaS HR SaaS Private npm
package UIコンポーネントライブラリの作成
©MNTSQ, Ltd. 9 ReactからVueへの転向: 思考の変化とアプローチの違い
©MNTSQ, Ltd. 10 目次 1. ライフサイクル表現の変化 2. 構文の変化 3. まとめ
©MNTSQ, Ltd. 11 目次 1. ライフサイクル表現の変化 2. 構文の変化 3. まとめ
©MNTSQ, Ltd. 12 ライフサイクル表現の変化
©MNTSQ, Ltd. 13 ライフサイクルの変化 React Vue useEffect lifecycle hook
©MNTSQ, Ltd. 14 ライフサイクルの変化 React Vue useEffect lifecycle hook
©MNTSQ, Ltd. 15 ライフサイクルの変化 React Vue useEffect() 1. update 2.
mount 3. unMount =
©MNTSQ, Ltd. 16 ライフサイクルの変化 useEffect() update mount unMount
©MNTSQ, Ltd. 17 どうやってuseEffectで 3つのlifecycleを表現しているのか?
©MNTSQ, Ltd. 18 ライフサイクルの変化 useEffectのlifecycle表現 const Component = () =>
{ useEffect( ()=>{ }, [ ] ) } 1. onMount 2. onUpdate 3. onUnmount
©MNTSQ, Ltd. 19 ライフサイクルの変化 const Component = () => {
useEffect(()=>{ // 1回目はonMount },[]) } 1. onMount ◦ Component()実行でuseEffect()も呼ばれる。 ◦ useEffectの初回実行がmount 2. onUpdate 3. onUnmount useEffectのlifecycle表現
©MNTSQ, Ltd. 20 ライフサイクルの変化 1. onMount ◦ Component()実行でuseEffect()も呼ばれる。 ◦ useEffectの初回実行がmount。
2. onUpdate ◦ useEffectの第2引数が変化する度に useEffectが再発火する。 ◦ state1, state2どちらが変わっても発火。 3. onUnmount const Component = () => { const [state1,] = useState() const [state2,] = useState() useEffect(()=>{ // 1回目はonMount // 2回目以降はonUpdate },[state1, state2]) // 依存配列 } useEffectのlifecycle表現
©MNTSQ, Ltd. 21 ライフサイクルの変化 1. onMount ◦ Component()実行でuseEffect()も呼ばれる。 ◦ useEffectの初回実行がmount。
2. onUpdate ◦ useEffectの第2引数が変化する度に useEffectが再発火する。 ◦ state1, state2どちらが変わっても発火。 3. onUnmount ◦ useEffectの第1引数の返り値がunmount。 const Component = () => { const [state1,] = useState() const [state2,] = useState() useEffect(()=>{ // 1回目はonMount // 2回目以降はonUpdate return () => {} // onUnmount },[state1, state2]) } useEffectのlifecycle表現
©MNTSQ, Ltd. 22 ライフサイクルの変化 なるほど!!
©MNTSQ, Ltd. 23 ライフサイクルの変化 useEffectはムズい
©MNTSQ, Ltd. 24 ライフサイクルの変化 useEffectムズい lifecycleを理解している人でないと (useEffectは)難しい
©MNTSQ, Ltd. 25 useEffectのなんのため?
©MNTSQ, Ltd. 26 ライフサイクルの変化 useEffectの恩恵は何?
©MNTSQ, Ltd. 27 ライフサイクルの変化 useEffectの恩恵は何? → 機能的な凝集性が高い
©MNTSQ, Ltd. 28 ライフサイクルの変化 useEffectの恩恵は何? → 機能的な凝集性が高い const Component =
() => { // API コール useEffect(()=> { const response = apiCall(payload) setResponse(response) }, [payload]) // タイマー処理 useEffect(()=>{ const timerId = setInterval(() => { // tick process }, 1000) return () => clearInterval(timerId) },[]) }
©MNTSQ, Ltd. 29 ライフサイクルの変化 useEffectの恩恵は何? → 機能的な凝集性が高い const Component =
() => { // API コール useEffect(()=> { const response = apiCall(payload) setResponse(response) }, [payload]) // タイマー処理 useEffect(()=>{ const timerId = setInterval(() => { // tick process }, 1000) return () => clearInterval(timerId) },[]) }
©MNTSQ, Ltd. 30 ライフサイクルの変化 useEffectの恩恵は何? → 機能的な凝集性が高い • APIコール ◦
mount時にAPIコール ◦ payloadのupdate時にAPIコール • タイマー ◦ mount時にタイマーをスタート ◦ unMount時にタイマーをクリア const Component = () => { // API コール useEffect(()=> { const response = apiCall(payload) setResponse(response) }, [payload]) // タイマー処理 useEffect(()=>{ const timerId = setInterval(() => { // tick process }, 1000) return () => clearInterval(timerId) },[]) }
©MNTSQ, Ltd. 31 ライフサイクルの変化 useEffectの恩恵は何? → 機能的な凝集性が高い • APIコール ◦
mount時にAPIコール ◦ payloadのupdate時にAPIコール • タイマー ◦ mount時にタイマーをスタート ◦ unMount時にタイマーをクリア const Component = () => { // API コール useEffect(()=> { const response = apiCall(payload) setResponse(response) }, [payload]) // タイマー処理 useEffect(()=>{ const timerId = setInterval(() => { // tick process }, 1000) return () => clearInterval(timerId) },[]) } 機能的な凝集性が高い→再利用がしやすい
©MNTSQ, Ltd. 32 lifecycle hookは?
©MNTSQ, Ltd. 33 ライフサイクルの変化 lifecycle hookの恩恵は?
©MNTSQ, Ltd. 34 ライフサイクルの変化 lifecycle hookの恩恵は? → 時間的な凝集性が高い
©MNTSQ, Ltd. 35 ライフサイクルの変化 lifecycle hookの恩恵は? → 時間的な凝集性が高い export default
{ watch: { payload: { this.fetchData(); } // APIコール }, mounted() { this.fetchData(); // APIコール this.timerId = setInterval(this.tick, 1000); // タイマー処理 }, beforeUnmount() { clearInterval(this.timerId); // タイマー処理 } };
©MNTSQ, Ltd. 36 ライフサイクルの変化 lifecycle hookの恩恵は? → 時間的な凝集性が高い export default
{ watch: { payload: { this.fetchData(); } // APIコール }, mounted() { this.fetchData(); // APIコール this.timerId = setInterval(this.tick, 1000); // タイマー処理 }, beforeUnmount() { clearInterval(this.timerId); // タイマー処理 } };
©MNTSQ, Ltd. 37 ライフサイクルの変化 lifecycle hookの恩恵は? → 時間的な凝集性が高い export default
{ watch: { payload: { this.fetchData(); } // APIコール }, mounted() { this.fetchData(); // APIコール this.timerId = setInterval(this.tick, 1000); // タイマー処理 }, beforeUnmount() { clearInterval(this.timerId); // タイマー処理 } }; • update ◦ APIコール • mount ◦ APIコール ◦ タイマースタート • unMount ◦ タイマーをクリア
©MNTSQ, Ltd. 38 ライフサイクルの変化 lifecycle hookの恩恵は? → 時間的な凝集性が高い export default
{ watch: { payload: { this.fetchData(); } // APIコール }, mounted() { this.fetchData(); // APIコール this.timerId = setInterval(this.tick, 1000); // タイマー処理 }, beforeUnmount() { clearInterval(this.timerId); // タイマー処理 } }; • update ◦ APIコール • mount ◦ APIコール ◦ タイマースタート • unMount ◦ タイマーをクリア 時間軸で機能は分断される。 物理的なまとまりが無いので機能の関連性を見 つけるのは難しい。
©MNTSQ, Ltd. 39 useEffect と lifecycle比較
©MNTSQ, Ltd. 40 ライフサイクルの変化 useEffect • update ◦ APIコール •
mount ◦ APIコール ◦ タイマースタート • unMount ◦ タイマーをクリア 時間的な凝集性が高い。 いつ何が起きるか分かりやすい。 機能が時間で切られて散らばる。 • APIコール ◦ mount時にAPIコール ◦ payloadのupdate時にAPIコール • タイマー ◦ mount時にタイマーをスタート ◦ unMount時にタイマーをクリア 機能的な凝集性が高い。 機能で再利用がしやすい。 発火タイミングを読み解く必要がある。 lifecycle hook
©MNTSQ, Ltd. 41 実装のアプローチ
©MNTSQ, Ltd. 42 ライフサイクルの変化 Composableのlifecycle hookが◎ Composableで機能的な凝集性が高い lifecycle hook郡を定義できる。 機能的な凝集性の高さを維持しつつ、
内部で発火タイミングも明確化。 function useInterval() { let timerId onMounted(() => { timerId = setInterval(() => { // tick process }, 1000) }); onUnmounted(() => { clearInterval(timerId) }); }
©MNTSQ, Ltd. 43 ライフサイクルの変化 function useInterval() { let timerId onMounted(()
=> { timerId = setInterval(() => { // tick process }, 1000) }); onUnmounted(() => { clearInterval(timerId) }); } Composableで機能的な凝集性が高い lifecycle hook郡を定義できる。 機能的な凝集性の高さを維持しつつ、 内部で発火タイミングも明確化。 Composableのlifecycle hookが◎
©MNTSQ, Ltd. 44 ライフサイクルの変化 function useInterval() { let timerId onMounted(()
=> { timerId = setInterval(() => { // tick process }, 1000) }); onUnmounted(() => { clearInterval(timerId) }); } Composableで機能的な凝集性が高い lifecycle hook郡を定義できる。 機能的な凝集性の高さを維持しつつ、 内部で発火タイミングも明確化。 Composableのlifecycle hookが◎ いいとこどり!
©MNTSQ, Ltd. 45 目次 1. ライフサイクル表現の変化 2. 構文の変化 3. まとめ
©MNTSQ, Ltd. 46 構文の変化
©MNTSQ, Ltd. 47 構文の変化 React(JSX) <Button className="red" onClick={submit} data-cy="submitButton" >
Save </Button> Vue(テンプレート) <Button class="red" @click="submit" data-cy="submitButton" > Save </Button>
©MNTSQ, Ltd. 48 構文の変化 React(JSX) <Button className="red" onClick={submit} data-cy="submitButton" >
Save </Button> Vue(テンプレート) <Button class="red" @click="submit" data-cy="submitButton" > Save </Button> 一番大きな変化
©MNTSQ, Ltd. 49 構文の変化 React(JSX) <Button className="red" onClick={submit} data-cy="submitButton" >
Save </Button> Vue(テンプレート) <Button class="red" @click="submit" data-cy="submitButton" > Save </Button> Vueには詳しいと思うので、、、
©MNTSQ, Ltd. 50 構文の変化 ReactのJSXって??
©MNTSQ, Ltd. 51 構文の変化 ReactのJSXって??
©MNTSQ, Ltd. 52 構文の変化 ReactのJSXって?? JSX (悪口が聞こえたような...)
©MNTSQ, Ltd. 53 構文の変化 ReactのJSXって?? 気持ち悪い ≒ よく知らないから?
©MNTSQ, Ltd. 54 JSXとは何者なのか?
©MNTSQ, Ltd. 55 構文の変化 JSXはJavaScriptの構文拡張 • テンプレート拡張じゃない • JavaScriptとXMLの組み合わせ •
ECMAScript2015に対する構文拡張 x =
©MNTSQ, Ltd. 56 構文の変化 JSXはJavaScriptの構文拡張 • テンプレート拡張じゃない • JavaScriptとXMLの組み合わせ •
ECMAScript2015に対する構文拡張 x = なにがJavaScriptに拡張されたの?
©MNTSQ, Ltd. 57 構文の変化 JSXはJavaScriptの構文拡張 • テンプレート拡張じゃない • JavaScriptとXMLの組み合わせ •
ECMAScript2015に対する構文拡張 x = なにがJavaScriptに拡張されたの? JSX.Element型
©MNTSQ, Ltd. 58 構文の変化 JSXはJavaScriptの構文拡張 • テンプレート拡張じゃない • JavaScriptとXMLの組み合わせ •
ECMAScript2015に対する構文拡張 • JSX.Element型が使える • TypeScriptが言語サポート x = const str: string = "hello world" const Element: JSX.Element = <span>hoge</span>
©MNTSQ, Ltd. 59 なぜReactはJSXなのか?
©MNTSQ, Ltd. 60 構文の変化 なぜReactはJSXなのか? →コンポーネントという関心の分離にフォーカスするため
©MNTSQ, Ltd. 61 構文の変化 なぜReactはJSXなのか? →コンポーネントという関心の分離にフォーカスするため
©MNTSQ, Ltd. 62 構文の変化 なぜReactはJSXなのか? →コンポーネントという関心の分離にフォーカスするため 分離すべきはコンポーネント。
©MNTSQ, Ltd. 63 構文の変化 なぜReactはJSXなのか? <template> <div></div> </template> <script> </script>
→コンポーネントという関心の分離にフォーカスするため 分離すべきはコンポーネント。
©MNTSQ, Ltd. 64 構文の変化 なぜReactはJSXなのか? <template> <div></div> </template> <script> </script>
→コンポーネントという関心の分離にフォーカスするため 分離すべきはコンポーネント。 UI・ロジックではない。 技術の分離は関心の分離には寄与しない。
©MNTSQ, Ltd. 65 構文の変化 なぜReactはJSXなのか? <template> <div></div> </template> <script> </script>
分離すべきはコンポーネント。 UI・ロジックではない。 技術の分離は関心の分離には寄与しない。 であれば一つの技術(JavaScript)の表現力を活かし コンポーネントの分離にフォーカスする。 JavaScriptドリブン →コンポーネントという関心の分離にフォーカスするため
©MNTSQ, Ltd. 66 構文の変化 なぜReactはJSXなのか? Reactチーム初期メンバー: Pete Hunt React rethinking
best practice Building components, not templates A framework cannot know how to separate your concerns for you. テンプレートではなくコンポーネントをつくる。 フレームワークは開発者がどのように関心の分離をするのか 分からない。
©MNTSQ, Ltd. 67 ではVueは?
©MNTSQ, Ltd. 68 構文の変化 Vueもやりたいことは同じ なぜSFCなのか(why-sfc) 関心の分離がファイルタイプの分離と同じではない コンポーネント内では、そのテンプレート、ロジック、およびスタイルが本質的に 結合されており、それらを連結することで、実際にコンポーネントがよりまとまり、 保守しやすくなります。
公式ドキュメントより
©MNTSQ, Ltd. 69 構文の変化 Vueもやりたいことは同じ なぜSFCなのか(why-sfc) 関心の分離がファイルタイプの分離と同じではない コンポーネント内では、そのテンプレート、ロジック、およびスタイルが本質的に 結合されており、それらを連結することで、実際にコンポーネントがよりまとまり、 保守しやすくなります。
SFCという概念が独立性の高いコンポーネントを作るギブス 公式ドキュメントより
©MNTSQ, Ltd. 70 構文の違い≒思想の違い
©MNTSQ, Ltd. 71 構文の変化 Webアプリケーションの捉え方 React Vue <template> <body> <header>
{{ header }} </header> <main> {{ content }} </main> <footer> {{ footer }} </footer> </body> <template> React React-pdf React Native アプリケーションのレンダリング先がブラウザ 動的なHTMLテンプレート
©MNTSQ, Ltd. 72 構文の変化 思考の切り替え React UI(JSX)を返す関数を書く // JSX {condition
&& <span>Visible</span>} <ul> {items.map(item => <li key={item.id}>{item.name}</li>)} </ul> <!-- Vue Template --> <span v-if="condition">Visible</span> <ul> <li v-for="item in items" :key="item.id">{{ item.name }}</li> </ul> Vue ディレクティブ等で動的なHTMLを作る
©MNTSQ, Ltd. 73 目次 1. 構文の変化 2. ライフサイクル表現の変化 3. まとめ
©MNTSQ, Ltd. 74 まとめ
©MNTSQ, Ltd. 75 まとめ まとめ • useEffectはムズい。 • lifecycle hookは機能的な凝集を意識
• ReactはJavaScriptドリブン • Vueは動的HTML ◦ (Vapor modeに期待)
©MNTSQ, Ltd. 76 ご清聴ありがとうございました。
None