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
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
540
Other Decks in Technology
See All in Technology
AIがコードを書く時代に、エンジニアは何で自分の価値を証明するのか / In an era where AI writes code how do engineers prove their value
carta_engineering
3
880
サブエージェントと Claude Mods で作る独自 Advisor ツールの話
kenichiodo
1
120
自作バイナリを動かす「入口」8選
puhitaku
2
1.3k
Deep Data Security 機能解説
oracle4engineer
PRO
2
800
Getting Started with Google Antigravity
glaforge
0
240
12 個 Tool と、 4,096 Token
hlum
0
150
「Docker Desktop不要の時代」は 来たのか?
ueponx
0
610
OR学会2026年秋期大会_機械学習と数理最適化の融合による、配合レシピ最適化システム開発事例
brainpadpr
0
140
宣言型部分更新は何を解決しどこへ向かうのか
shuta13
1
360
組み立てて楽しむ AWS Blocks 入門
kmiya84377
0
230
Loop Engineering, beyond prompt, context, and harness engineering
glaforge
0
100
AI時代のAPI開発を加速する品質ガードレール / API Quality Guardrails in the AI Era
yokawasa
0
190
Featured
See All Featured
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
320
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
2
940
Six Lessons from altMBA
skipperchong
29
4.5k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
600
Why Our Code Smells
bkeepers
PRO
340
58k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.9k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
330
Design in an AI World
tapps
1
350
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.6k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
3.1k
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
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