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
Shift-from-React-to-Vue
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
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
520
Other Decks in Technology
See All in Technology
Introduction to Sansan for Engineers / エンジニア向け会社紹介
sansan33
PRO
6
77k
tamachi.goを支える技術
rymiyamoto
0
120
Microsoft MVP プログラムを紹介するから目指す人増えてくれ
tsubakimoto_s
0
150
紙 to デジタル
ichien178
0
400
アクセスキー流出時の対応で再認識した攻撃側と防御側の非対称性について
kazzpapa3
1
450
顧客の要望は2次情報である 〜アンテナを張るFDEの構造論〜
noriakioji
5
1.1k
暗号化?某ファイルストレージはどうなるの!? 3rd Partyとうまく付き合う秘密度ラベル設計
kasada
0
220
サーバー常駐型の 簡易障害調査AI エージェントを作ってみた話
masayoshi
1
440
アクセスキーが漏れた日にやるべきこと- 無効化の先にある本当の対応
kazzpapa3
0
360
1000⼈規模のClaude Enterprise運⽤を「Oktaのグループ」と「Slack」に集約する
sansantech
PRO
1
520
信頼性はSREだけのものじゃない
hkawaras
0
340
型落ちシンクライアント端末のPoEモジュールを自作したかった話
logica0419
0
510
Featured
See All Featured
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.8k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
3k
Utilizing Notion as your number one productivity tool
mfonobong
4
560
Optimizing for Happiness
mojombo
378
71k
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
540
Into the Great Unknown - MozCon
thekraken
41
2.7k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
420
The Curse of the Amulet
leimatthew05
2
14k
Design in an AI World
tapps
1
290
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
310
Raft: Consensus for Rubyists
vanstee
141
7.7k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
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