6

I am using Vue.js with the vuex store. I call an API method to validate an item, the method returns an array of errors and an array of warnings.

My vuex action :

export function validateitemReview ({ commit, dispatch, state }, { reviewId, type, itemreviewData }) {
  console.log('*** validateItemReview() called')
  return api.post(`/clients/districts/reviews/${reviewId}/${type}/validate`, itemreviewData).then(response => {
    console.log('response.data :')
    console.log(response.data)
    commit('setItemReviewsErrors', 'teststring')
  })
}

As you can see, i'm not doing much with the response yet. The called setItemReviewsErrors mutation in the vuex store :

export const setItemReviewsErrors = (state, data) => {
  console.log('*** setItemReviewsErrors() called, data:')
  console.log(data)
}

Here comes my problem, my console output is the following :

*** validateItemReview() called
response.data :
{
    fatal_errors: []
    warnings: []
    __proto__: Object
}
*** setItemReviewsErrors() called, data:
teststring

directly followed by this error :

Uncaught (in promise) TypeError: Converting circular structure to JSON
    at JSON.stringify (<anonymous>)
    at eval (vuex-persistedstate.es.js?0e44:1)
    at eval (vuex-persistedstate.es.js?0e44:1)
    at eval (vuex.esm.js?2f62:392)
    at Array.forEach (<anonymous>)
    at Store.commit (vuex.esm.js?2f62:392)
    at Store.boundCommit [as commit] (vuex.esm.js?2f62:335)
    at local.commit (vuex.esm.js?2f62:651)
    at eval (itemreview_actions.js?0d87:62)

itemreview_actions.js?0d87:62 is the following line in my vuex validateitemReview() action:

commit('setItemReviewsErrors', 'teststring')

if I comment it, no more error. I can't figure where could be my "circular structure" when the problems seems to come from committing a simple string.

Even better, why:

  • my console.log() from the setItemReviewsErrors mutation is still printed and the error comes after even though the error seems to be while calling this method
  • If I reload the page (Ctrl+R in browser), there are no errors but if I leave it (go to another page) and then come back to it, the error is thrown again.

Update

The problem seems to come from the plugin vuex-persistedstate . I found out that the vuex store of this application is using it. I am not alone with this problem :

But the dev just closes the tickets. If anyone has a lead to solve that, I am not allowed to remove the persistence plugin.

halfer
  • 19,824
  • 17
  • 99
  • 186
Tom
  • 1,357
  • 2
  • 13
  • 32
  • Use a parser that supports circular json. https://github.com/WebReflection/flatted – Brian Lee Dec 02 '18 at 10:40
  • this could be a workaround but there is no reason JSON thinks there is a circular structure here, so i'd like to solve that first – Tom Dec 02 '18 at 10:43
  • a [JSON](http://json.org/) is a string. how can it contain a circular reference? – Nina Scholz Dec 02 '18 at 10:49
  • I'm obviously missing something because indeed, how is this possible ? – Tom Dec 02 '18 at 10:52
  • problem seems to be comming from vuex-persistedstate plugin (question updated) – Tom Dec 02 '18 at 11:58
  • 1
    @Tom I had exactly the same problem using this plugin (https://github.com/robinvdvleuten/vuex-persistedstate/issues/146#issuecomment-442808260) My code work well without this plugin but fail to convert my JSON when it's enabled. I just remove it from my dependencies and rework a little my code to have the same behavior. The dev seem to close all the issues about this error but I think their is a problem inside the plugin code. – Jérôme Dec 02 '18 at 15:01
  • @Jérôme I changed the plugin and I have kind of the same problem. Sadly I need a persistence plugin, I cannot just remove it :( – Tom Dec 02 '18 at 15:05
  • 1
    If you want I can explain to you how I made it to work. But it depend of your needs (and if you have the same need as me) but it not related with this question. – Jérôme Dec 02 '18 at 15:08
  • Thank you, I found another workaround, I don't need to use the store for this specific feature now, but this leaves this question unsolved.... – Tom Dec 02 '18 at 15:47
  • It's an interesting question. Looking at vuexpersistedstate index.js it just calls JSON.stringify in one place with `return storage.setItem(key, JSON.stringify(state))`, so your state must have the circular reference, which may cause other problems even if you remove vuexpersistedstate. Could you post your state? – Richard Matsen Dec 02 '18 at 20:11
  • This is likely the root problem you need to solve [JSON.stringify, avoid TypeError: Converting circular structure to JSON](https://stackoverflow.com/questions/11616630/json-stringify-avoid-typeerror-converting-circular-structure-to-json/11616993). It may be more subtle, as Vuex state is dynamic and the circular refernce only occurs after a certain mutation. – Richard Matsen Dec 02 '18 at 20:16

1 Answers1

7

See this alternate library, vuex-persist, they meet this problem head-on

If you have circular structures in your state

let x = { a: 10 }  
x.x = x  
x.x === x.x.x // true  
x.x.x.a === x.x.x.x.a //true  

JSON.parse() and JSON.stringify() will not work.

You'll need to install circular-json

npm install circular-json

And when constructing the store, add supportCircular flag

new VuexPersistence({
  supportCircular: true,
  ...
})

However, a circular reference in state may cause you other problems, if at some stage a reactive property triggers another call to the same mutation. That said, you would likely see the problem quickly as a Maximum call stack size exceeded error.

See the comment by Linus Borg on this code

mutations:
saveVideoComment(state, {id, text, videoId}) {
    let comment = {
        id: id,
        videoId: videoId,
        text: text,
        inlineUserVideo: state.userVideos[userVideoId]
    };
    Vue.set(state.videoComments, id, comment);
    state.videos[videoId].comments.push(id);
    state.videos[videoId].inlineComments.push(comment);
}
Richard Matsen
  • 20,671
  • 3
  • 43
  • 77
  • Even though my boss told me i spent enough time on that and I found another workaround, this seems to be an acceptable answer, thank you ! – Tom Dec 04 '18 at 08:55
  • 2
    LOL You're welcome. Tell your boss you are saving future rework! – Richard Matsen Dec 04 '18 at 09:07