Skip to content
This repository has been archived by the owner on Dec 5, 2024. It is now read-only.

fix: Vuex mutation error when using useFetch #584

Open
aaronhuisinga opened this issue Nov 16, 2021 · 10 comments
Open

fix: Vuex mutation error when using useFetch #584

aaronhuisinga opened this issue Nov 16, 2021 · 10 comments
Assignees
Labels
bug Something isn't working

Comments

@aaronhuisinga
Copy link

aaronhuisinga commented Nov 16, 2021

🐛 The bug
In some instances using Vuex with useFetch can result in the following error: [vuex] do not mutate vuex store state outside mutation handlers..

It appears that having an object with a value set to either an array or an object is enough to trigger this error. Any simple data type or an object containing only simple data types (strings, numbers, etc) will not trigger it.

This only occurs when manipulating the store item within a useFetch call, and returning the computed property from the setup method.

Example that will not cause issue:

{ id: 11, name: 'Test Person' }

Example that will cause issue:

{ id: 11, roles: [1, 2] }

🛠️ To reproduce
Steps to reproduce the behavior:

  1. Setup Vuex store, page, and Nuxt Composition API
  2. Set item from Vuex store to computed property, and return from setup method.
  3. Manipulate the item in the Vuex store within a useFetch method. The item must be an object, and have a property set to either an object or array.

Reproduction: https://stackblitz.com/edit/nuxt-starter-vylpg5?devtoolsheight=33&file=pages%2Findex.vue

🌈 Expected behaviour
The expected behavior is for the item to not be mutated outside of mutation handlers, and successfully render.

@aaronhuisinga aaronhuisinga added the bug Something isn't working label Nov 16, 2021
@aaronhuisinga
Copy link
Author

@danielroe It appears this issue started with v0.28.0. My guess is it's due to #541.

@Dell-it
Copy link

Dell-it commented Feb 9, 2022

@aaronhuisinga Hello, I met with the same problem, did you manage to solve/work around it somehow?

@aaronhuisinga
Copy link
Author

@aaronhuisinga Hello, I met with the same problem, did you manage to solve/work around it somehow?

For the time being I've just locked the package at v0.27.0. That has all of the functionality I need anyway and works as expected.

You could also start the upgrade to Nuxt 3 using Nuxt Bridge. There is quite a bit of work to do if you've been using this package, and I'm not sure how stable it is, so proceed at your own risk there. I started the process for one of the Nuxt apps I maintain, but decided to wait until more functionality was implemented before continuing.

@adrianwix
Copy link

I faced the same issue and it was driving me insane. This needs an urgent fix

@adrianwix
Copy link

adrianwix commented Apr 4, 2022

@danielroe Any update on it? Not being able to update the store inside useFetch is messing up all the business logic in my app. If I use onMounted I get a bunch of server-side errors in other components. If I use composables I have to fetch the same entity every single time.

I won't migrate to nuxt-bridge until it is stable

@danielroe
Copy link
Member

danielroe commented Apr 4, 2022

You should not manipulate the store within useFetch. Instead use useAsync, which does not stringify the entire component state.

@janvacek
Copy link

@danielroe ok, but if you use useAsync, it will be called twice - server side and then client side - or not?

Copy link
Member

No, it will not.

@janvacek
Copy link

@danielroe look at this issue, I have the same problem with useAsync #652, thats why I wrote my last comment, it is called twice even with simple example

@adrianwix
Copy link

@danielroe One question how do you use useAsync then to fetch data where you have 2 API calls and the second call depends on the first one? What my team end up doing is the following

const user = ref()
const documents = ref()
/**
* fetchUser and fetchDocument are defined here and set the values above
*/
async function initiateMethods() {
            user = await fetchUser()
            documents = await fetchDocuments()
}
useAsync(() => initiateMethods())

in this the right way? from my understanding if useAsync is analogous to asyncData it should be something like

async function initiateMethods() {
            const user = await fetchUser()
            const documents = await fetchDocuments(user.id)
            return { user, documents }
}

// here user and documents should be both reactive references. But since asyncData returns only one reactive object
const { user, documents } = useAsync(() => initiateMethods())

// should we do this?
const data = useAsync(() => initiateMethods())
const user = ref(data?.user || null)
const documents = ref(data?.documents || null)

I am asking here because we face these doubts because of the error mentioned in this thread. I think it is not clear enough how to use it in the nuxt composition plugin and sadly Nuxt/Vue 3 ecosystem needs like 6 more months to be usable (e.g Vuetify 3 is not yet ready for Vue 3)

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

No branches or pull requests

5 participants