Search code examples
firebasevue.jsvuejs2vuexvuex4

How do I remove a Firestore snapshot listener from a Vuex store


I am trying to figure out how to remove a snapshot listener from my vue3/vuex store. I have seen the answers to other similar questions and the many links to the Firestore docs, but I cannot figure out WHERE in the vuex store to put the call to unsubscribe(). Could someone help with where and how to call the unsubscribe() function while using vuex?

I have a component that is calling to the bindAccts() in the store, which then runs a commit/mutation and populates my "accounts state. Here is the code I have in my vuex store file:

import { createStore } from 'vuex'
import { db } from '../main'

export default createStore({
  state() {
    return { categories: [], accounts: [], transactions: [], count: 1 }
  },
  mutations: {
    SET_ACCTS(state, data) {
      state.accounts = data
    },

  },
  actions: {
    bindAccts({ commit }) {
      this.unsubscribe = db
        .collection('accounts')
        .onSnapshot(function(querySnapshot) {
          let accounts = []
          querySnapshot.forEach(function(doc) {
            accounts.push(doc.data())
          })
          commit('SET_ACCTS', accounts)
        })
    },
...

Inside my test component I am calling bindAccts() like this and just quickly displaying the accounts state on the ui:

<template>
  <button @click="bindAccts">Subscribe</button>
  <button @click="unsubscribe">Unsubscribe</button>
  <p>Accounts: {{ accounts }}</p>
</template>

<script>
import { mapActions, mapState } from 'vuex'
export default {
  components: {},

  data() {
    return {}
  },

  computed: {
    ...mapState({ accounts: state => state.accounts })
  },

  methods: {
    ...mapActions(['bindAccts', 'unsubscribe'])
  }
}
</script>

<style></style>

Doing this I am unable to find the unsubscribe function.


Solution

  • There are two possible solutions:

    Return unsubscribe function from action and call in component

    1. In your Vuex action, return the unsubscribe from bindAccts({ commit }).
    2. In your component, for the Subscribe button onClick handler function (a new one), you call the bindAccts and store the returned function in local data or a variable.
    3. Then, when the user clicks Unsubscribe, you call the local stored unsubscribe if defined.

    Or

    Save unsubscribe in your Vuex store

    1. The idea would be to save the unsubscribe variable in your existing Vuex store as a state variable and use Getters and Mutations to get/set the variable (same as other properties in your current state).
    2. Then, you can add unsubscribe as another Vuex action, and in your component, use mapActions to map the action as a method. The logic would be quite straightforward.