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
Vue.js 状態管理の選択肢 - そのVuex本当に必要ですか - / Vue.js Sta...
Search
ryo
March 17, 2021
Technology
4.8k
7
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Vue.js 状態管理の選択肢 - そのVuex本当に必要ですか - / Vue.js State Management Options
iCARE Dev Meetup #19 2021/03/17
ryo
March 17, 2021
More Decks by ryo
See All by ryo
Bridging Social Graphs
kawamataryo
0
350
Raycast AI APIを使ってちょっと便利なAI拡張機能を作ってみた
kawamataryo
1
600
退屈なことはDevinにやらせよう〜〜Devin APIを使ったVisual Regression Testの自動追加〜
kawamataryo
5
2.3k
SaaS公式MCPサーバーをリリースして得た学び
kawamataryo
7
2.2k
Raycast AI APIを使ってちょっと便利な拡張機能を作ってみた / created-a-handy-extension-using-the-raycast-ai-api
kawamataryo
1
910
ts-morphのパフォーマンス改善Tips
kawamataryo
0
140
webpack to Rspack
kawamataryo
0
140
GitHub Actions と Datadog でコードベースの定点観測
kawamataryo
7
2.1k
個人開発駆動学習 / personal development driven learning
kawamataryo
1
320
Other Decks in Technology
See All in Technology
俺の仕事は AIに奪われないし、たぶんその BIも要らない
hikaruri
0
490
Azure Serverless 2026:Production-ready な AI エージェント基盤 / Azure Serverless 2026: Production-Ready AI Agent Platform
miyake
1
130
AI に書かせたその API、 “信頼” できますか?
nagix
0
110
新機種発売前に見直そう!端末移行で再ログインが要るアプリ・要らないアプリは何が違うのか 〜シームレスに再開できる設計と実装〜
zozotech
PRO
0
200
「ピッケル本」日本語版は4.0(第6版)が出版されるべき / pickaxe4-nagoyark05
kakutani
1
150
Railsのように考える: See through the Master
snoozer05
PRO
3
920
DEFCON34-Write-up_HYCu-MYCu
daikiokazaki
0
160
iOSDC Japan 2026 day1 TrackC 10:50
feedtailor
1
160
アクセスキーこわい やめかたと漏らさない工夫
sassssan68
1
310
負債のメタファと2026年 / Debt Metaphor in Agentic Engineering Age 202609 Edition
twada
PRO
8
3.5k
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
3
510
生成AIエージェントを用いた、 手動テスト手順書から自動テストへの 変換手法の検討
magicpod
0
160
Featured
See All Featured
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
580
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
280
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.7k
Skip the Path - Find Your Career Trail
mkilby
1
230
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
203
76k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.8k
Become a Pro
speakerdeck
PRO
31
6.3k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
The Art of Programming - Codeland 2020
erikaheidi
57
14k
Designing Powerful Visuals for Engaging Learning
tmiket
1
550
Transcript
Vue.js ঢ়ଶཧͷબࢶ ʙ ͦͷVuexຊʹඞཁͰ͔͢? ʙ @KawamataRyo 2021/03/17 iCARE Dev Meetup
#19
ࣗݾհ
@KawamataRyo LAPRAS גࣜձࣾ TypeScript, Vue, Firebase, Ruby ݩফ࢜🔥🚒
ࠓ͢͜ͱ
Vuex + α ͷঢ়ଶཧख๏ͷհ ͦΕͧΕͷ Pros/Cons ͷ·ͱΊ
ͳͥঢ়ଶཧΛςʔϚʹʁ🤔
Vuex ݏΘΕ͗͢͡Όͳ͍͔..?
Vuex 😭 🐵 🐶 😼 🦁 🐯 🐻 🐹 🦊
ͦΕͬͯຊʹVuexͷͳͷͩΖ͏͔ʁ
VuexΛ దʹར༻Ͱ͖ͯͳ͍ or దͳॴͰར༻Ͱ͖ͯͳ͍ ߹͋Δͷ͔ʁ
VuexΛ దʹར༻Ͱ͖ͯͳ͍ or దͳॴͰར༻Ͱ͖ͯͳ͍ ߹͋Δͷ͔ʁ
Vuex Ҏ֎ͷঢ়ଶཧΛΔ͜ͱͰ ঢ়ଶཧͷબࢶΛ͍͛ͨ
ঢ়ଶཧͷجຊ
ͦͦঢ়ଶཧͱʁ
ΞϓϦ͕࣋ͭ ঢ়ଶʢσʔλʣΛదʹѻ ͍ΞϓϦΛਖ਼͘͠ಈ࡞ͤ͞ Δํ๏
ͳͥঢ়ଶཧϥΠϒϥϦ͕ඞཁʁ
ίϯϙʔωϯτ͕૿͑Δͱ Props/EmitͰͷঢ়ଶͷ ͕ෳࡶʹ..
ೝূใͳͲෳίϯϙʔωϯτ Ͱڞ௨ͷσʔλɾϩδοΫΛ࣋ͪ ͍ͨ..
ෳͷίϯϙʔωϯτ͔Β ΞΫηεͰ͖Δάϩʔόϧͳ ঢ়ଶ͕ඞཁ => ঢ়ଶཧϥΠϒϥϦ
ঢ়ଶཧͷબࢶ
Vuex Pinia Vue Apollo Composition API Store
Vuex Pinia Vue Apollo Composition API Store
- Vueެࣜͷঢ়ଶཧϥΠϒϥϦ - FluxϥΠΫ - ୯Ұ Store vuejs / vuex
(v4)
Store import { InjectionKey } from "vue"; import { createStore,
Store } from "vuex"; export interface State { count: number; } export const key: InjectionKey<Store<State>> = Symbol(); export const store = createStore<State>({ state: { count: 0 }, mutations: { increment(state) { state.count++; }, decrement(state) { state.count--; } }, actions: { increment({ commit }) { commit("increment"); }, decrement({ commit }) { commit("decrement"); } } });
Store import { InjectionKey } from "vue"; import { createStore,
Store } from "vuex"; export interface State { count: number; } export const key: InjectionKey<Store<State>> = Symbol(); export const store = createStore<State>({ state: { count: 0 }, mutations: { increment(state) { state.count++; }, decrement(state) { state.count--; } }, actions: { increment({ commit }) { commit("increment"); }, decrement({ commit }) { commit("decrement"); } } }); createStoreͰstoreΛఆٛ mutations, actionsͰstateΛૢ࡞
Store import { InjectionKey } from "vue"; import { createStore,
Store } from "vuex"; export interface State { count: number; } export const key: InjectionKey<Store<State>> = Symbol(); export const store = createStore<State>({ state: { count: 0 }, mutations: { increment(state) { state.count++; }, decrement(state) { state.count--; } }, actions: { increment({ commit }) { commit("increment"); }, decrement({ commit }) { commit("decrement"); } } }); provide/inject༻ͷΩʔ ʢTSͷܕఆٛऔಘͷͨΊʣ
Install import { createApp } from "vue"; import App from
"./App.vue"; import { store, key } from "./stores/vuex/store"; const app = createApp(App); // vuex app.use(store, key); app.mount("#app");
Install import { createApp } from "vue"; import App from
"./App.vue"; import { store, key } from "./stores/vuex/store"; const app = createApp(App); // vuex app.use(store, key); app.mount("#app"); storeͱkeyΛొ
Components (read) <script lang="ts"> import { defineComponent, computed } from
"vue"; import { useStore } from "vuex"; import { key } from "@/stores/vuex/store"; export default defineComponent({ name: "Counter", setup() { const store = useStore(key); const count = computed(() => store.state.count); return { count }; } }); </script>
Components (read) <script lang="ts"> import { defineComponent, computed } from
"vue"; import { useStore } from "vuex"; import { key } from "@/stores/vuex/store"; export default defineComponent({ name: "Counter", setup() { const store = useStore(key); const count = computed(() => store.state.count); return { count }; } }); </script> keyΛͯ͠storeΛऔಘ countnumberܕͱͯ͠ਪ
<script lang="ts"> import { defineComponent } from "vue"; import {
useStore } from "vuex"; import { key } from "@/stores/vuex/store"; export default defineComponent({ name: "IncrementButton", setup() { const store = useStore(key); const increment = () => store.dispatch("increment"); return { increment }; } }); </script> Components (write)
<script lang="ts"> import { defineComponent } from "vue"; import {
useStore } from "vuex"; import { key } from "@/stores/vuex/store"; export default defineComponent({ name: "IncrementButton", setup() { const store = useStore(key); const increment = () => store.dispatch("increment"); return { increment }; } }); </script> Components (write) dispatchͰactionsΛ࣮ޮ ܕิޮ͔ͳ͍
- ެࣜϥΠϒϥϦ - υΩϡϝϯτɾࢀߟใͷ๛͞ - DevToolsͷ࿈ܞ - ߏԽ͞ΕͨύλʔϯʢFluxʣ - SSRରԠ
Pros 😁
- TypeScriptͷܕ͚ͷରԠ - هड़ྔͷଟ͞ Cons 😵
Vuex Pinia Vue Apollo Composition API Store
- Composition APIઐ༻ - ܰྔʢ1kbະຬʣ - ෳStore posva / pinia
Store import { defineStore } from "pinia"; export const useCounterStore
= defineStore({ id: "counter", state: () => ({ count: 0 }), actions: { increment() { this.count++; }, decrement() { this.count--; } } });
Store import { defineStore } from "pinia"; export const useCounterStore
= defineStore({ id: "counter", state: () => ({ count: 0 }), actions: { increment() { this.count++; }, decrement() { this.count--; } } }); mutationsͳ͘actionsͰ stateΛૢ࡞ storeݻ༗ͷ idΛ࣋ͭ
Install import { createApp } from "vue"; import App from
"./App.vue"; import { createPinia } from "pinia"; const app = createApp(App); // pinia app.use(createPinia()); app.mount("#app");
Install import { createApp } from "vue"; import App from
"./App.vue"; import { createPinia } from "pinia"; const app = createApp(App); // pinia app.use(createPinia()); app.mount("#app"); piniaͷrootετΞΛొ
Components (read) <script lang="ts"> import { defineComponent, computed } from
"vue"; import { useCounterStore } from "@/stores/pinia/store"; export default defineComponent({ name: "Counter", setup() { const store = useCounterStore(); const count = computed(() => store.count); return { count }; } }); </script>
Components (read) <script lang="ts"> import { defineComponent, computed } from
"vue"; import { useCounterStore } from "@/stores/pinia/store"; export default defineComponent({ name: "Counter", setup() { const store = useCounterStore(); const count = computed(() => store.count); return { count }; } }); </script> numberܕͱͯ͠ਪ exportͨ͠StoreΛར༻
<script lang="ts"> import { defineComponent } from "vue"; import {
useCounterStore } from "@/stores/pinia/store"; export default defineComponent({ name: "IncrementButton", setup() { const store = useCounterStore(); const increment = () => store.increment(); return { increment }; } }); </script> Components (write)
<script lang="ts"> import { defineComponent } from "vue"; import {
useCounterStore } from "@/stores/pinia/store"; export default defineComponent({ name: "IncrementButton", setup() { const store = useCounterStore(); const increment = () => store.increment(); return { increment }; } }); </script> Components (write) actionsͷ ܕิ͕ޮ͘
Demo https://vue-state-management-samples.vercel.app/pinia
- TypeScript શରԠ - DevToolsͷ࿈ܞʢݱঢ়ࢀরͷΈʣ - γϯϓϧͳίʔυ - SSRରԠ Pros
😁
- ใྔͷগͳ͞ - ਖ਼ࣜϦϦʔεલ - ։ൃͷܧଓੑ Cons 😵
Vuex Pinia Composition API Store vue-apollo
- Composition APIͰ ಠ࣮ࣗͨ͠Store Composition Store
Store import { reactive, provide, InjectionKey, toRefs } from "vue";
import { DeepReadonly } from "utility-types"; export const createStore = () => { const state = reactive({ count: 0 }); const actions = { increment: () => { state.count++; }, decrement: () => { state.count--; } }; return { state: toRefs(state), actions }; }; type Store = ReturnType<DeepReadonly<typeof createStore>>; export const STORE_KEY: InjectionKey<Store> = Symbol("Store"); export const useStore = () => { return inject(STORE_KEY) as Store; };
Store import { reactive, provide, InjectionKey, toRefs } from "vue";
import { DeepReadonly } from "utility-types"; export const createStore = () => { const state = reactive({ count: 0 }); const actions = { increment: () => { state.count++; }, decrement: () => { state.count--; } }; return { state: toRefs(state), actions }; }; type Store = ReturnType<DeepReadonly<typeof createStore>>; export const STORE_KEY: InjectionKey<Store> = Symbol("Store"); export const useStore = () => { return inject(STORE_KEY) as Store; }; reactiveͰstateΛఆٛ ؔͰstateΛૢ࡞
Store import { reactive, provide, InjectionKey, toRefs } from "vue";
import { DeepReadonly } from "utility-types"; export const createStore = () => { const state = reactive({ count: 0 }); const actions = { increment: () => { state.count++; }, decrement: () => { state.count--; } }; return { state: toRefs(state), actions }; }; type Store = DeepReadonly<ReturnType<typeof createStore>>; export const STORE_KEY: InjectionKey<Store> = Symbol("Store"); export const useStore = () => { return inject(STORE_KEY) as Store; }; provide/inject༻ͷ ؔɾΩʔ DeepReadolyͰ stateͷॻ͖͑Λېࢭ্ͨ͠Ͱ InjectionKeyͷܕʹઃఆ
Install import { createApp, provide } from "vue"; import App
from "./App.vue"; import { STORE_KEY, createStore } from "@/stores/originalStore/store"; const app = createApp(App); // Original Store app.provide(STORE_KEY, createStore()); app.mount("#app");
import { createApp, provide } from "vue"; import App from
"./App.vue"; import { STORE_KEY, createStore } from "@/stores/originalStore/store"; const app = createApp(App); // Original Store app.provide(STORE_KEY, createStore()); app.mount("#app"); Install Storeͷ࡞ͱprovideͰͷొ
Components (read) <script lang="ts"> import { defineComponent, computed } from
"vue"; import { useStore } from "@/stores/originalStore/store"; export default defineComponent({ name: "Counter", setup() { const { state } = useStore(); const count = computed(() => state.count.value); return { count }; } }); </script>
Components (read) <script lang="ts"> import { defineComponent, computed } from
"vue"; import { useStore } from "@/stores/originalStore/store"; export default defineComponent({ name: "Counter", setup() { const { state } = useStore(); const count = computed(() => state.count.value); return { count }; } }); </script> injectͰͷstoreͷऔಘ numberܕͱͯ͠ਪ
<script lang="ts"> import { defineComponent } from "vue"; import {
useStore } from "@/stores/originalStore/store"; export default defineComponent({ name: "IncrementButton", setup() { const { actions } = useStore(); const increment = () => actions.increment(); return { increment }; } }); </script> Components (write)
<script lang="ts"> import { defineComponent } from "vue"; import {
useStore } from "@/stores/originalStore/store"; export default defineComponent({ name: "IncrementButton", setup() { const { actions } = useStore(); const increment = () => actions.increment(); return { increment }; } }); </script> Components (write) ୯७ͳؔݺͼग़͠ ͳͷͰܕิ͕ޮ͘
Demo https://vue-state-management-samples.vercel.app/original-store
- TypeScript શରԠ - γϯϓϧͳίʔυ - ґଘͳ͠ Pros 😁
- ΦϨΦϨStoreͷ - DevTools ࿈ܞ - vue-routerɺSSRͷରԠ Cons 😵
Vuex Pinia Vue Apollo Composition API Store
- Apollo CacheΛStoreʹ - Query / MutationͰͷૢ࡞ vuejs / vue-apollo
GraphQLͷεΩʔϚఆٛ import gql from "graphql-tag"; export const typeDefs = gql`
extend type Store { count: Int! } extend type Mutation { increment: Int decrement: Int } extend type Query { CountQuery: Store } `;
Queryͷఆٛ import gql from "graphql-tag"; export const COUNT_QUERY = gql`
query CountQuery { store @client { count } } `;
Queryͷఆٛ import gql from "graphql-tag"; export const COUNT_QUERY = gql`
query CountQuery { store @client { count } } `; @clientͱσΟϨΫςΟϒΛ͚ͭΔ͜ͱͰɺ αʔόʔʹ͍߹ΘͤͣɺΩϟογϡͰॲཧ͢Δ
import gql from "graphql-tag"; export const INCREMENT_MUTATION = gql` mutation
incrementMutation { increment @client } `; export const DECREMENT_MUTATION = gql` mutation decrementMutation { decrement @client } `; Mutationͷఆٛ
Resolvers import { InMemoryCache } from "apollo-cache-inmemory"; import { COUNT_QUERY
} from "@/stores/apolloClient/queries"; export const resolvers = { Mutation: { increment: ( _: unknown, _arg: unknown, { cache }: { cache: InMemoryCache }) => { const data = cache.readQuery<any>({ query: COUNT_QUERY }); data.store.count++; cache.writeQuery({ query: COUNT_QUERY, data }); return data.store.count; }, decrement: ( _: unknown, _arg: unknown, { cache }: { cache: InMemoryCache }) => { const data = cache.readQuery<any>({ query: COUNT_QUERY }); data.store.count--; cache.writeQuery({ query: COUNT_QUERY, data }); return data.store.count; } } };
Resolvers import { InMemoryCache } from "apollo-cache-inmemory"; import { COUNT_QUERY
} from "@/stores/apolloClient/queries"; export const resolvers = { Mutation: { increment: ( _: unknown, _arg: unknown, { cache }: { cache: InMemoryCache }) => { const data = cache.readQuery<any>({ query: COUNT_QUERY }); data.store.count++; cache.writeQuery({ query: COUNT_QUERY, data }); return data.store.count; }, decrement: ( _: unknown, _arg: unknown, { cache }: { cache: InMemoryCache }) => { const data = cache.readQuery<any>({ query: COUNT_QUERY }); data.store.count--; cache.writeQuery({ query: COUNT_QUERY, data }); return data.store.count; } } }; queryͷcacheΛॻ͖͍͑ͯΔ
Apollo Clientͷ࡞ import ApolloClient from "apollo-boost"; import { typeDefs }
from "@/stores/apolloClient/typeDefs"; import { InMemoryCache } from "apollo-cache-inmemory"; import { resolvers } from "@/stores/apolloClient/resolvers"; const cache = new InMemoryCache(); export const apolloClient = new ApolloClient({ cache, typeDefs, resolvers }); // storeͷॳظԽ cache.writeData({ data: { store: { __typename: "Store", count: 0 } } });
Apollo Clientͷ࡞ import ApolloClient from "apollo-boost"; import { typeDefs }
from "@/stores/apolloClient/typeDefs"; import { InMemoryCache } from "apollo-cache-inmemory"; import { resolvers } from "@/stores/apolloClient/resolvers"; const cache = new InMemoryCache(); export const apolloClient = new ApolloClient({ cache, typeDefs, resolvers }); // storeͷॳظԽ cache.writeData({ data: { store: { __typename: "Store", count: 0 } } }); cacheͷॳظԽॲཧ
Install import { createApp } from "vue"; import App from
"./App.vue"; import { DefaultApolloClient } from "@vue/apollo-composable"; import { apolloClient } from "@/stores/apolloClient/apolloClient"; const app = createApp(App); // vue-apollo app.provide(DefaultApolloClient, apolloClient); app.mount("#app");
Install import { createApp } from "vue"; import App from
"./App.vue"; import { DefaultApolloClient } from "@vue/apollo-composable"; import { apolloClient } from "@/stores/apolloClient/apolloClient"; const app = createApp(App); // vue-apollo app.provide(DefaultApolloClient, apolloClient); app.mount("#app"); Apollo ClientΛprovide
Components (read) <script lang="ts"> import { defineComponent } from "vue";
import { useQuery, useResult } from "@vue/apollo-composable"; import { COUNT_QUERY } from "@/stores/apolloClient/queries"; export default defineComponent({ name: "Counter", setup() { const { result } = useQuery(COUNT_QUERY); const count = useResult(result, 0, data => data.store.count); return { count }; } }); </script>
Components (read) <script lang="ts"> import { defineComponent } from "vue";
import { useQuery, useResult } from "@vue/apollo-composable"; import { COUNT_QUERY } from "@/stores/apolloClient/queries"; export default defineComponent({ name: "Counter", setup() { const { result } = useQuery(COUNT_QUERY); const count = useResult(result, 0, data => data.store.count); return { count }; } }); </script> GraphQL QueryͰऔಘ
Components (write) <script lang="ts"> import { defineComponent } from "vue";
import { useMutation } from "@vue/apollo-composable"; import { INCREMENT_MUTATION } from "@/stores/apolloClient/mutations"; export default defineComponent({ name: "IncrementButton", setup() { const { mutate: increment } = useMutation(INCREMENT_MUTATION); return { increment }; } }); </script>
<script lang="ts"> import { defineComponent } from "vue"; import {
useMutation } from "@vue/apollo-composable"; import { INCREMENT_MUTATION } from "@/stores/apolloClient/mutations"; export default defineComponent({ name: "IncrementButton", setup() { const { mutate: increment } = useMutation(INCREMENT_MUTATION); return { increment }; } }); </script> Components (write) MutationͰॻ͖͑
Demo https://vue-state-management-samples.vercel.app/vue-apollo
- StoreΛ࣋ͨͳ͍ - DevToolsʢApolloʣରԠ Pros 😁
- Vue ApolloɺGraphQLͷґଘ - ঢ়ଶͷѲ͕ͮ͠Β͍ - ։ൃͷܧଓੑ - ίʔυྔͷ૿Ճ Cons
😵
·ͱΊ
7VFY 1JOJB $PNQPTJUJPO"1* 4UPSF 7VF"QPMMP 4UPSFͷ ୯Ұ ෳ ෳ ʢΩϟγϡʣ
%FW5PPMTରԠ ˓ ˚ º ˚ʢ"QPMMPʣ 5ZQF4DSJQUରԠ ˚ ˓ ˓ ˚ ଟػೳੑ ʢ443FUDʣ ˓ ˚ º º ίʔυͷهड़ྔ ˚ ˓ ˓ º
ࠓͷVueͷঢ়ଶཧVuex͚ͩͰͳ͍ɻ ΞϓϦέʔγϣϯͷنॏࢹ͢Δʹ ߹Θͤͯదͳঢ়ଶཧख๏Λબ ͢Δ͜ͱ͕େ
ࢀߟ • you might not need Vuex: https://speakerdeck.com/ntepluhina/you-might-not-need-vuex • Do
you really need Vuex: https://blog.logrocket.com/do-you-really-need-vuex • ΈΜͳͷVue.js: https://gihyo.jp/book/2021/978-4-297-11902-7 • Pinia vs Vuex: https://www.youtube.com/watch?v=ht_1NR7OFWc • intro to vuex: https://www.vuemastery.com/courses/mastering-vuex/intro-to-vuex/ • Pinia doc: https://pinia.esm.dev/ • Vuex4 doc: https://next.vuex.vuejs.org/
͓·͚ Vuex 5 RFCͷ·ͱΊ 2021/03/14 ࣌ https://github.com/kiaking/rfcs/blob/vuex-5/active-rfcs/0000-vuex-5.md
Storeͷఆٛ Storeͷར༻ Mutationsͷഇࢭ dispatchΛհͣ͞ actionsΛݺΔ ᶃ FluxϥΠΫύλʔϯΛഇࢭ
Optional Store Composition Store ΄΅Composition APIͦͷ·· ᶄ 2छྨͷStoreఆٛํ๏
Store 1 Store 2 ωετ͞ΕͨStoreʢModuleʣ Λഇࢭͯ͠ɺComposition Ͱ Storeͷ૬ޓར༻Λߦ͏ ᶅωετ͞ΕͨStoreΛഇࢭ
Store Component Optional Storeͷ߹ ܕΞϊςʔγϣϯΛ͚ͭΔ ʢComposition StoreͰෆཁʣ ༻࣌ ܕิ͕શʹޮ͘ ᶆ
શͳTypeScriptαϙʔτ