nuxt-fire-vuexfire-example
nuxt-fire-vuexfire-example copied to clipboard
bindFirestoreRef behaviour differs between fetch() and mounted()
Weird behaviour that is causing me some problems. Might not understand something here but I get different behaviour calling the same Vuex store action from different places. I'm checking my browser console and vs code terminal (due to SSR) but can't find the console.logs I expect:
rules/actions.js
export default {
bindRuleDocument: firestoreAction(async function (
{ bindFirestoreRef },
{ ruleId, source }
) {
console.log(
'Attempting rule document binding with received id',
ruleId,
'from',
source
)
const docRef = await this.$fire.firestore
.collection('rules')
.where('id', '==', ruleId)
console.log('docRef received for source', source, docRef)
return await new Promise((resolve, reject) => {
bindFirestoreRef('currentRuleDocument', docRef, { wait: true })
.then((res) => {
console.log('Response in bindRuleDocument', res)
if (!res.length) {
throw new Error('No such document')
} else {
console.log('Received rule for source call from', source)
// TODO Display snackbar message
//commit('SET_SNACKBAR_MESSAGE', 'Rule bound')
return resolve(res)
}
})
.catch((err) => {
console.log('Error in bindRuleDocument', err)
//commit('SET_SNACKBAR_MESSAGE', err.message)
return reject(err)
})
})
}),
The above codes is called from the fetch() and the mounted() hook as mentioned by @lupas to avoid server-side memory leaks and bind on the client-side after loading data on server-side for SSR.
Here are the calls: rule.vue (page)
/** Bind Vuexfire on server-side: */
async fetch() {
console.log('In rules/_id.vue/fetch() with', this.$route.params.id)
let isInitialPageLoad = !this.$nuxt.context.from
console.log('isInitialPageLoad', isInitialPageLoad)
// TODO Not sure if I should be doing this? Why should data be fetched again on client-side?
// if (process.browser) {
// console.log('In browser in _id.vue', process.browser)
// return
// }
// if (isInitialPageLoad) {
await this.$store
.dispatch('rules/bindRuleDocument', {
ruleId: this.$route.params.id,
source: 'rules/_id.vue/fetch()',
})
.then((res) => console.log('Returned response from ruleBinding is', res))
.then((res) => {
this.$store.dispatch('rules/unbindRuleDocument')
console.log(
'Fetch completed with',
this.$store.state.rules.currentRuleDocument[0]
)
})
.catch((err) => {
console.log('Received rejected promise from ruleBinding:', err)
this.$router.push('/')
})
// }
},
and the mounted() function:
/** Bind Vuexfire on client-side: */
async mounted() {
this.isLoading = true
console.log('In rules/_id.vue/mounted() with', this.$route.params.id)
try {
await this.$store
.dispatch('rules/bindRuleDocument', {
ruleId: this.$route.params.id,
source: 'rules/_id.vue/mounted()',
})
.then((res) => {
this.isLoading = false
console.log(
'Mounted rules/bindRuleDocument with',
this.$store.state.rules.currentRuleDocument[0].id
)
})
} catch (err) {
this.isLoading = false
console.error('Error rules/_id.vue/mounted()', err)
}
},
rules/mutations.js
import { vuexfireMutations } from 'vuexfire'
export default {
...vuexfireMutations,
SET_RULES_COLLECTION: (state, rulesCollection) => {
// Only needed for SSR/Universal Mode
state.rules.rulesCollection = rulesCollection
console.log('Bound rulesCollection', state.rules.rulesCollection)
},
SET_RULE_DOCUMENT: (state, ruleDocument) => {
// Only needed for SSR/Universal Mode
state.rules.ruleDocument = ruleDocument
console.log('Bound ruleDocument', state.rules.ruleDocument)
},
}
rules/state.js
export const getDefaultState = () => {
// console.log('In rules/getDefaultState')
return {
rulesCollection: [],
ruleDocument: {},
}
}
const state = getDefaultState()
export default {
state,
}
The results in the following console.log in the browser when navigating to an individual rule:
19:57:56.020 In rules/_id.vue/fetch() with 0EJfHC2LP71DeNS1NX9D _id.vue:39
19:57:56.020 isInitialPageLoad false _id.vue:42
19:57:56.021 Attempting rule document binding with received id 0EJfHC2LP71DeNS1NX9D from rules/_id.vue/fetch() actions.js:9
19:57:56.023 In rules/_id.vue/mounted() with 0EJfHC2LP71DeNS1NX9D _id.vue:83
19:57:56.023 Attempting rule document binding with received id 0EJfHC2LP71DeNS1NX9D from rules/_id.vue/mounted() actions.js:9
19:57:56.024 docRef built for source
Object { d_: {…}, firestore: {…}, Xf: {…} }
rules/_id.vue/fetch() actions.js:19
19:57:56.026 docRef built for source
Object { d_: {…}, firestore: {…}, Xf: {…} }
rules/_id.vue/mounted() actions.js:19
19:57:56.036 Response in bindRuleDocument
Array [ {…} ]
actions.js:23
19:57:56.037 Received rule for source call from rules/_id.vue/mounted() actions.js:27
19:57:56.037 Mounted rules/bindRuleDocument with 0EJfHC2LP71DeNS1NX9D
vs code console:
» Updated store\rules\actions.js 19:57:50
√ Client - Compiled successfully in 768.99ms
√ Server - Compiled successfully in 816.34ms
TL;DR:
- Fetch attempts rulebinding
- Mounted attempts rulebinding
- Both report successful docRef creation
- Mounted returns the data from firestore but fetch's call disappears into the Nirvana.
What am I missing here? Thanks!! (Just to mentioned it: This leads to weird loading behaviour, where fetch.loading does not finish, the rule data isn't set when using getters, etc.)
// EDIT1: I am referring to this demo repo store.js file: https://github.com/lupas/nuxt-fire-vuexfire-example/blob/master/store/index.js and added my rules/mutations.js