Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix getters being destroyed on component destroy (#1878) #1883

Merged
merged 5 commits into from Oct 4, 2021

Conversation

kiaking
Copy link
Member

@kiaking kiaking commented Nov 22, 2020

fix #1878

This PR aims to fix #1878, but at the moment this is just adding failing test case.

The problem we have is that when component gets destroyed, the getters (computed) get's destroyed via Vue. Hence if we call registerModule inside a component, any newly registered computed will disappear when that component gets destroyed, for example, when switching route.

The issue: vuejs/core#1532
Solution RFC: vuejs/rfcs#212

We have to wait for Vue 3.1 3.2 to completely resolve this issue.

@kiaking kiaking added bug Something isn't working 4.x labels Nov 22, 2020
@kiaking kiaking self-assigned this Nov 22, 2020
kawamataryo added a commit to kawamataryo/zenn-articles that referenced this pull request Feb 24, 2021
diff --git a/articles/intoroduce-vuex4-with-composition-api.md b/articles/intoroduce-vuex4-with-composition-api.md
new file mode 100644
index 0000000..4a963b7
--- /dev/null
+++ b/articles/intoroduce-vuex4-with-composition-api.md
@@ -0,0 +1,432 @@
+---
+title: "Vuex4 を Composition API + TypeScript で入門する"
+emoji: "️️🔋"
+type: "tech"
+topics: ["vuex", "vue", "typescript"]
+published: true
+---
+
+今月初めにリリースされた Vuex4 を Composition API + TypeScript で試してみたのでそのメモです。
+この記事は以下バージョンにて検証しています。
+- [vuejs/vue](https://github.com/vuejs/vue) 3.0.5
+- [vuejs/vuex](https://github.com/vuejs/vuex) 4.0.0
+
+# Vuexとは?
+Vuex は、Vue.js 公式の状態管理ライブラリです。
+Vue アプリケーション内に、どの階層のコンポーネントからでもデータを取得・更新できる単一のデータストアを作ることができます。Vuex を使うことで複数のコンポーネントで使う共有データの Props/Emit による過剰なバケツリレーが不要になります。
+
+また、複雑になりがちな状態管理において以下の図のように特定のルールで制約を与えることでデータの流れを一元化して、コードの構造と保守性を向上させることができます。
+
+![](https://i.gyazo.com/57159fbe2e8c50e475808076c325832f.png)
+([What is Vuex?](https://next.vuex.vuejs.org/))
+
+# 使い方
+Vue CLI で Vue3 + TypeScript の環境構築が行われている前提で、簡単な Todo アプリの状態管理を例に Vuex の一連の流れをみていきます。
+
+## インストール + 初期設定
+
+まず Vuex を依存に追加します。
+
+:::message
+Vuex4 は 2021/02/24 時点で vuex ではなく vuex@next というパッケージ指定なので注意してください。
+:::
+
+```
+yarn add vuex@next --save
+```
+
+つぎに Vuex のストアの構造を定義する`store.ts`を作成します。
+
+```
+mkdir src/store
+touch store/store.ts
+```
+
+```ts:src/store/store.ts
+import { InjectionKey } from 'vue';
+import { createStore, Store, useStore as baseUseStore } from "vuex";
+
+// stateの型定義
+type State = {};
+
+// storeをprovide/injectするためのキー
+export const key: InjectionKey<Store<State>> = Symbol();
+
+// store本体
+export const store = createStore<State>({});
+
+// useStoreを使う時にキーの指定を省略するためのラッパー関数
+export const useStore = () => {
+  return baseUseStore(key);
+}
+```
+
+`useStore`のラッパー関数はなくても良いのですが、毎回コンポーネントでストアを取得するために`useStore(key)`と key を指定するのが面倒なので定義しています。コンポーネントからは`store.ts`の`userStore()`を使うようにします([参考](https://next.vuex.vuejs.org/guide/typescript-support.html#simplifying-usestore-usage))。
+
+そしてストアを`main.ts`でプラグインとして設定します。
+
+```ts:main.ts
+import { createApp } from "vue";
+import App from "./App.vue";
+import { key, store } from "./store/store";
+
+const app = createApp(App);
+
+app.use(store, key);
+
+app.mount("#app");
+```
+
+これで準備は完了です。
+
+## State
+state は Vuex で管理する状態そのものです。state はリアクティブなデータとなり、state の変更は Vue.js の変更検知の対象となります。
+
+### ストアでの定義
+
+まず `store.ts`で state の型定義を追加します。
+
+```ts:store.ts
+// ...
+type TodoItem = {
+  id: number;
+  title: string;
+  content: string;
+  completed: boolean;
+};
+
+type State = {
+  todoItems: TodoItem[];
+};
+// ...
+```
+
+そしてストアの実装である`createStore`の引数オブジェクトに`state`プロパティを追加して初期値を設定します。
+
+```ts:store.ts
+// ...
+export const store = createStore<State>({
+   state: {
+     todoItems: [
+      {
+         id: 1,
+        title: "foo",
+        content: "bar",
+        completed: false
+      }
+    ]
+  }
+});
+// ...
+```
+
+### コンポーネントでの利用
+
+state の利用は`store.ts`に定義した`useStore`を使います。ラッパー関数にて`provide/inject`のキーは設定しているので、この場でキーの指定は不要です。
+
+```vue:src/store/store.ts
+<template>
+  <div>
+    <div v-for="item in todoItems" :key="item.id">
+      <p>{{ item.title }}</p>
+      <p>{{ item.content }}</p>
+      <p>{{ item.completed ? "" : "-" }}</p>
+      <hr />
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent, computed } from "@vue/runtime-core";
+import { useStore } from "@/store/store"; // store/store.tsのものを利用
+
+export default defineComponent({
+  setup() {
+    const store = useStore();
+    const todoItems = computed(() => store.state.todoItems);
+
+    return {
+      todoItems
+    };
+  }
+});
+</script>
+```
+
+`store.sate`で取得できる値は`store.ts`で型定義した`type State`の型が設定されています。 なので state は型安全に使えます。
+
+```ts
+// 例
+// idはnumberと推論される
+const id = store.state.todoItems[0].id
+```
+
+## Mutations
+mutations は state を変更する関数です。
+Vuex で state を変更する際は直接 state を書き換えるのではなく、必ず mutation を経由して行うのが Vuex のルールです。
+
+### ストアでの定義
+
+まず、mutation の関数名を管理する`mutationType.ts`を作成します。
+関数名を定数や Enum で一元管理しておくと、後述する commit の際に定数で指定できるので便利です。
+
+```ts:src/store/mutationType.ts
+export const ADD_TODO_ITEM = "ADD_TODO_ITEM";
+```
+
+次に`store.ts`の createStore の引数のオブジェクトに mutations をプロパティを追加します。
+mutation の関数の第 1 引数には state、第 2 引数には後述する commit の際の引数を受け取れます。その引数を使って関数の内部で state を更新します。
+
+
+```ts:src/store/store.ts
+// ...
+import * as MutationTypes from "./mutationTypes";
+
+// ...
+export const store = createStore<State>({
+  // ...
+  mutations: {
+    [MutationTypes.ADD_TODO_ITEM](state, todoItem: TodoItem) {
+      state.todoItems.push(todoItem);
+    }
+  }
+});
+```
+
+### コンポーネントでの利用
+コンポーネント側での mutations の実効は`store.commit`を使います。
+以下 TodoItem を追加する例です。
+
+```vue:src/components/TodoItemForm.vue
+<template>
+  <form>
+    <label for="title">
+      title
+      <input type="text" id="title" v-model="form.title" />
+    </label>
+    <label for="content">
+      content
+      <input type="text" id="content" v-model="form.content" />
+    </label>
+    <input type="submit" value="submit" @click.prevent="onSubmit" />
+  </form>
+</template>
+
+<script lang="ts">
+import { defineComponent, reactive } from "@vue/runtime-core";
+import { useStore } from "@/store/store";
+import * as MutationTypes from "@/store/mutationTypes";
+
+export default defineComponent({
+  setup() {
+    const form = reactive({
+      title: "",
+      content: ""
+    });
+
+    const clearForm = () => {
+      form.title = "";
+      form.content = "";
+    };
+
+    const store = useStore();
+
+    const onSubmit = () => {
+      store.commit(MutationTypes.ADD_TODO_ITEM, {
+        id: Math.floor(Math.random() * 100000), // 仮でランダムなIDを設定
+        content: form.content,
+        title: form.title
+      });
+      clearForm();
+    };
+
+    return {
+      onSubmit,
+      form
+    };
+  }
+});
+</script>
+```
+
+state の変更は、`onSubmit`の`store.commit`部分で行っています。
+第 1 引数に mutation の関数名の文字列(ここでは mutationTypes の定数を利用)を指定して、第 2 引数で対象の mutation に渡す引数を指定しています。
+
+```ts
+const onSubmit = async () => {
+  await store.commit(MutationTypes.ADD_TODO_ITEM, {
+    id: Math.floor(Math.random() * 100000), // 仮でランダムなIDを設定
+    content: form.content,
+    title: form.title
+  });
+  clearForm();
+};
+```
+
+注意する点として、mutation は同期的に実効されます。非同期処理を mutation の関数内で行はないようにしてください。
+※ mutation 内部で非同期処理を書くことは出来ますが、store.commit が Promise を返さないので非同期処理を待つことが出来ない。
+
+:::message
+コンポーネントから mutation を実効せず、必ず後述の actions を介して mutation を実効という思想もあります。記述は増えますがそちらのほうがストアのデータの流れはシンプルになるので良さそうな気がします。
+:::
+
+## Actions
+action は同期・非同期を問わない state に関するあらゆる操作を定義するものです。
+一般的には非同期処理を含む state の変更のトリガーに用いられます。
+
+### ストアでの定義
+TodoItems の初期値を API 経由で取得する例です。
+action も mutation と同様に定数で管理するためにまず`actionTypes.ts`を追加します。
+
+```ts:src/store/actinonTypes.ts
+export const INITIALIZE_TODO_ITEMS = "INITIALIZE_TODO_ITEMS";
+```
+
+store の変更は mutation 経由して行うので`mutationTypes.ts`にも定数を追加します。
+
+```ts:src/store/mutationTypes.ts
+// ...
+export const INITIALIZE_TODO_ITEMS = "INITIALIZE_TODO_ITEMS";
+```
+
+次に`store.ts`の createStore の引数のオブジェクトに actions プロパティを追加します。
+actions の関数の第 1 引数には`state`, `commit`, `getters`を含むオブジェクトが受け取れます。actions の関数で async/await を使うことで非同期処理をハンドルできます。
+
+```ts:src/store/store.ts
+// ...
+import * as ActionTypes from "./actionTypes";
+
+// ...
+export const store = createStore<State>({
+  // ...
+  mutations: {
+    // ...
+    [MutationTypes.INITIALIZE_TODO_ITEMS](store, todoItems: TodoItem[]) {
+      store.todoItems = todoItems;
+    }
+  },
+  actions: {
+    async [ActionTypes.INITIALIZE_TODO_ITEMS]({ commit }) {
+      const todoItems = await fetchAllTodoItems(); // TodoItemsを取得するAPIコール
+      commit(ActionTypes.INITIALIZE_TODO_ITEMS, todoItems);
+    }
+  }
+});
+```
+
+今回は todoItem の一覧を取得する`fetchAllTodoItems`を実効してその戻値を mutation を介して TodoItems の初期化に使っています。
+
+
+### コンポーネントでの利用
+
+コンポーネントから action を利用する場合は`store.dispatch`を使います。
+以下はコンポーネントがマウントされるタイミングで dispatch を呼ぶ例です。dispatch は Promise を返すので async/await で処理を待つことができます。
+
+```vue:src/components/TodoItems.vue
+<!-- ... -->
+
+<script lang="ts">
+import { defineComponent, computed } from "@vue/runtime-core";
+import { useStore } from "@/store/store"; // store/store.tsのものを利用
+import * as ActionTypes from "@/store/actionTypes"
+
+export default defineComponent({
+  async setup() {
+    const store = useStore();
+    const todoItems = computed(() => store.state.todoItems);
+
+    onMounted(async () => {
+      await store.dispatch(ActionTypes.INITIALIZE_TODO_ITEMS)
+    })
+
+    return {
+      todoItems
+    };
+  }
+});
+</script>
+```
+
+ここでは dispatch に引数を渡していませんが、引数を受け取る Actions の場合は第 2 引数で Actions に渡す引数を指定出来ます。
+
+## Getters
+getter は state からの算出データを定義するものです。state に何らかの処理をした値を複数の場所で利用する場合は、 getter を定義しておくと便利です。
+
+
+### ストアでの定義
+`store.ts`の createStore の引数のオブジェクトに getters プロパティを追加して、完了済みの TodoItems を取得する getter を定義します。
+
+```ts:src/store/store
+export const store = createStore<State>({
+  // ...
+  getters: {
+    completedTodoItems: store => {
+      return store.todoItems.filter(todo => todo.completed);
+    }
+  }
+}
+```
+
+:::message
+Vue 3.0 の場合は Vue2 系と違い getter の結果がキャッシュされないという不具合があるようです。これは[こちらのPR](vuejs/vuex#1883
+Vue 3.1 で解消される見込みとのことです。
+:::
+
+### コンポーネントでの利用
+
+コンポーネントでは`store.getters`で利用出来ます。
+ただ、state と違い`store.getters`の戻値は any なので型推論が効きません。
+
+```vue:src/components/completedTodoItems.vue
+<!-- ... -->
+<script lang="ts">
+import { defineComponent, computed } from "@vue/runtime-core";
+import { useStore } from "@/store/store"; // store/store.tsのものを利用
+
+export default defineComponent({
+  setup() {
+    const store = useStore();
+    const todoItems = computed(() => store.getters.completedTodoItems); // todoItemsはComputedRef<any>と推論される
+
+    return {
+      todoItems
+    };
+  }
+});
+</script>
+```
+
+# その他考慮点
+使ってみてわかった Vuex4 採用に関する考慮点を書きます。
+
+## TypeScriptの対応がまだ不完全
+
+Vuex の課題として長らく上がっているのが TypeScript への対応だと思います。
+commit、dispatch、getters をタイプセーフに実効することが出来ず、型補完を効かせるには [vuex-type-helper](https://github.com/ktsn/vuex-type-helper) 等のプラグインを別途使う必要がありました。
+
+TypeScript 4.1 で template literal types が入ったことですし Vuex4 で何らかの改善があるのかなと期待してたところですが、まだ完全な対応は難しいようです。
+Vuex4 でも Vuex3 と同様、commit、dispatch、getters で型補完は効きません。別 Plugin を利用するか、独自で型定義を設定して何らかの対応をする必要があるようです。
+
+(独自で型定義する例)
+https://dev.to/shubhadip/vue-3-vuex-4-modules-typescript-2i2o
+
+## mapHelpersがComposition APIでは使えない
+Vue4 + Composition API の場合の現状の問題点が、複数のストア操作を一括で定義できる mapHelpers(`mapState`、 `mapGetters`、`mapActions`、`mapMutations`)が使えないことです。
+※ Vuex4 でも Option API を使う場合は mapHelpers を使えます。
+
+Vuex を使っている場合はほぼ mapHelpers を使っていると思うので、Vuex4 + Composition API の書き換えの障害になると思われます。
+
+一応以下の Issue が上がっています。早く実装されると良いですね。
+
+vuejs/vuex#1725
+
+# 終わりに
+
+以上、Vuex4 + Composition API + TypeScript の簡単な紹介でした。
+TypeScript の対応や mapHelpers など今すぐの採用は迷うところですが、引き続き動向を追っていきたいです。
+その他 Vuex の Moudule 機能が中々ややこしいのでまた別でまとめようと思っています。
+
+# 参考
+
+- [Vuex公式ドキュメント](https://next.vuex.vuejs.org/)
+- [みんなのVue.js:書籍案内|技術評論社](https://gihyo.jp/book/2021/978-4-297-11902-7)
\ No newline at end of file
saiful-semantic added a commit to saiful-semantic/vuex that referenced this pull request Jun 23, 2021
PR vuejs#1878 link fixed. Updated status as per PR vuejs#1883
@4refael
Copy link

4refael commented Aug 7, 2021

The lack of cache for getters is causing heavy performance issues in some situations.
Will this be fixed with the release of Vue 3.2? seems like the new API is merged.

@chuski1212
Copy link

Hey! Any news about this? Vue 3.2 has been officially released.

@kiaking kiaking force-pushed the 1878-getters-destroyed-on-component-destroy branch from 0989895 to f3abade Compare Aug 18, 2021
@kiaking kiaking requested a review from posva Aug 18, 2021
@kiaking
Copy link
Member Author

kiaking commented Aug 18, 2021

@posva I've added effect scope support on getters creation. Could give it a review and see if it looks good? 🙏

In Vuex 4, we create computed (getters) object during the resetStore function, which will be called on registerModule method. So, I think this is the only place we need to care. For example, we don't have watch feature in module, hence watch will always be called outside of the setup hook (on store creation), so I don't think we have to worry about it.

Copy link
Member

@posva posva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good although I haven't tried locally. I wasn't so sure about creating a new scope and disposing of the old one, is that for HMR? Isn't it possible to just create one and always use the same?

test/helpers.js Outdated Show resolved Hide resolved
test/unit/modules.spec.js Outdated Show resolved Hide resolved
test/unit/modules.spec.js Show resolved Hide resolved
src/store-util.js Show resolved Hide resolved
@kiaking
Copy link
Member Author

kiaking commented Aug 19, 2021

@posva

I wasn't so sure about creating a new scope and disposing of the old one, is that for HMR? Isn't it possible to just create one and always use the same?

Maybe we can? If we re-run the same scope, wouldn't the effects stack up? Since we would be re-creating all getters every time a module is added, I thought we should dispose old effects. Not sure 👀 Let me check on it.

UPDATE: Confirmed that we should dispose the old effect other wise they will live forever.

@brianrlewis
Copy link

brianrlewis commented Aug 31, 2021

Any progress on this? I'm very eager to upgrade to vue 3 but can't do it until vuex getters are cached properly.

@phil294
Copy link

phil294 commented Sep 7, 2021

I appreciate the work that is being put into this and understand it is not exactly a trivial fix, but could you please add a big red warning at the front page of https://next.vuex.vuejs.org/, discouraging the use of Vuex 4? Getters don't seem to cache anything, at all, not just on component destroy, as far as I have observed. I just spent several work days migrating a few codebases to Vue 3, just to realize it isn't usable yet. In some cases, performance of Vuex went from 100 ms to > 2 minutes, obviously breaking the app.

Not trying to nag, but please put an appropriate note at the top of Vuex 4 landing page.

@jkosir
Copy link

jkosir commented Sep 22, 2021

Also appreciate all the work going into this and hopefully this doesn't come off too mean, but how come this is simply getting ignored for 1+ months? The way I see it it's essentially a blocker for Vuex 4.0 adoption in most Vue 3 apps.

@tirithen
Copy link

I'm part of a team that recently created an app starting from vue 3 and vuex 4. We did not realize these performance issues at first, we assumed that vuex 4 would be a better version of version 3.

Now when our system is built we see that in many cases where we need to use a larger set of input fields, the user interface is locked due to performance issues.

We are currently working on refactoring the code to use as few store bindings that we possibly can. Could you revert the cache changes to the ones from the previous version until that part is more mature?

We like using vuex, we choose it since it is the official store for vue, but if it looks like it takes several months more to resolve this critical problem we might need to switch to redux or similar, so any hints on how long it would take would be greatly appreciated.

I just also wanted to say that we appreciate a lot all the work that has been done on both vue and vuex, for small apps it probably works great, and hopefully, soon it will work for more complex apps as well.

Keep up the good work! :)

@kiaking
Copy link
Member Author

kiaking commented Sep 29, 2021

@tirithen This is going to be merged soon. Sorry it's taking long but meanwhile, you can build this branch directly and apply the fix manually.

@tirithen
Copy link

@kiaking That sounds wonderful! Thank you for the fast reply, I'll definitely give it a try to use a build from this branch meanwhile!

Thanks again for all the work being put in!

@kiaking kiaking merged commit b2f851f into 4.0 Oct 4, 2021
9 checks passed
@kiaking kiaking deleted the 1878-getters-destroyed-on-component-destroy branch Oct 4, 2021
@phil294
Copy link

phil294 commented Oct 14, 2021

The getters caching seems to work fine with this PR, but the reactivity system does not. Maybe this is expected, I'm not sure - but for anyone following this thread, I don't think you just can use the 4.0 branch as is already, at least in my test project, when going from 4.0.2 release to 4.0 branch, vue templates didn't update anymore when the underlying vuex state changed.

@kiaking
Copy link
Member Author

kiaking commented Oct 15, 2021

@phil294 Can you provide example code for this? At least examples in the examples folder is working I think. There might be some edge cases?

@phil294
Copy link

phil294 commented Oct 15, 2021

@phil294 Can you provide example code for this? At least examples in the examples folder is working I think. There might be some edge cases?

Sure! I just did: Looks more like a setup problem. I could reproduce it on the examples folder by installing vue in the example folder. Here's a bash command to test it out:
git clone https://github.com/vuejs/vuex && cd vuex && git checkout 4.0 && npm i && pushd examples/classic/counter && npm init -y && npm add vue@next && popd && npm run dev, then open http://localhost:8080/classic/counter/, aaaand: the buttons don't do anything.

@kiaking
Copy link
Member Author

kiaking commented Oct 18, 2021

Ahhhh OK, not 100% sure but I think this is because Vuex and the Project are using different Vue bundle. Thanks for the clue!

@blaz-rupnik
Copy link

We also tested out this branch because we are in the process of migrating to Vue 3.0 and the reduced performance of getters is a blocker for us.

I tested this fix by pointing the vuex package to this branch:

"dependencies": {
    "vuex": "git://github.com/vuejs/vuex.git#4.0",
}

What happens now is that we have reactivity issues. In one of our components we have:

<div class="application__sidebar" v-if="isRouteValid">
    <sidebar />
 </div>
.
.
.
computed: {
    ...mapState([
        'isRouteValid',
    ]),
}

So isRouteValid is in our store and false by default. Once you enter the site we use router.afterEach for updating the isRouteValid to true. But the component doesn't rerender now. I checked if maybe mutation wasn't triggering but it does. Hope this can help as a replication procedure.

@phil294
Copy link

phil294 commented Dec 12, 2021

@kiaking am I right to assume this is still broken? Are there any plans on mending this issue and releasing the fix? Can we help you anyhow? I'm not sure I can figure out this dependency problem in any reasonable amount of time, but I could try. Do you need a PR?
We would love to finally switch to Vue 3. But we can't, Vuex 4 is still essentially unusable :-/

@jkosir
Copy link

jkosir commented Jan 3, 2022

No this is still not fixed properly and even this fix isn't released. In Vuejs live UK conf (https://twitter.com/vue_london) on October 20th 2021 every stage-management discussion was focused into Pinia with no mention of any future development of Vuex.

In Q&A there was a question about this issue specifically, we were told it will be looked into soon™️

@thomasdao
Copy link

thomasdao commented Jan 10, 2022

Not sure if anyone has experience with Pinia, does it have the problem with getters like Vuex?

EDIT: I migrated from Vuex to Pinia, Pinia works really well and doesn't have this problem with getters.

@bill-kasa
Copy link

Any updates?

@nbgraham
Copy link

nbgraham commented Apr 9, 2022

this fix introduced another bug, breaking reactivity (even worse than before)

#2102 @phil294

Could you be more specific about how this is breaking or provide reproduction code?
I know you provided some steps above,

git clone https://github.com/vuejs/vuex && cd vuex && git checkout 4.0 && npm i && pushd examples/classic/counter && npm init -y && npm add vue@next && popd && npm run dev, then open http://localhost:8080/classic/counter/

but that seems like it might be caused by some weird bundling

I think this is because Vuex and the Project are using different Vue bundle

I wasn't able to reproduce this issue in a new project. I assumed it meant that changes to getters would not "trigger" updates on computeds, but all the reactivity and caching worked fine for me.
I created a new vue app (npm init vue@latest which was version 3.2.31) and added vuex from the commit right after the #1883 merge (b2f851f)

const store = createStore({
  state() {
    return {
      count: 0,
    };
  },
  getters: {
    count(state) {
      console.log("computing count getter");
      return state.count;
    },
    countPlusOne(state, getters) {
      console.log("computing count plus one getter");
      return getters.count + 1;
    },
  },
  mutations: {
    increment(state) {
      state.count++;
    },
  },
});
<script setup lang="ts">
import { computed } from "vue";
import { useStore } from "vuex";

const store = useStore();
const stateCount = computed(() => store.state.count);
const gettersCount = computed(() => store.getters.count);
const gettersCountPlusOne = computed(() => store.getters.countPlusOne);
const increment = () => store.commit("increment");
</script>

<template>
  <div>
    <div>State Count: {{ stateCount }}</div>
    <div>Getters Count: {{ gettersCount }}</div>
    <div>Getters Count Plus One: {{ gettersCountPlusOne }}</div>
    <button @click="increment">Increment</button>
  </div>
  <template />
</template>

@phil294
Copy link

phil294 commented Apr 11, 2022

Could you be more specific about how this is breaking or provide reproduction code? [...] I assumed it meant that changes to getters would not "trigger" updates on computeds

Yes that is exactly what was going on. I also gave up and migrated to Pinia, so I cannot give you up to date code on that anymore, sorry - apart from the reproduction instructions you already saw.

but that seems like it might be caused by some weird bundling

Yeah well but I guess that's the problem then? Or are you suggesting these are two separate bugs? I don't know, but I assumed otherwise.

@rendomnet
Copy link

This issue still not fixed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4.x bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet