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

Cannot stringify POJOs with symbolic keys on nuxt 2 #163

Closed
kieusonlam opened this issue Oct 1, 2018 · 15 comments
Closed

Cannot stringify POJOs with symbolic keys on nuxt 2 #163

kieusonlam opened this issue Oct 1, 2018 · 15 comments

Comments

@kieusonlam
Copy link
Collaborator

Version

v4.0.0-rc.2

Reproduction link

https://github.com/nuxt-community/apollo-module

Steps to reproduce

I get this error after update nuxt 2.0.0 to 2.1.0, revert back to 2.0.0 still geting the problem. It's happen on my both 2 project when return the value that query by apollo in asyncData:

  async asyncData({ error, app, params }){
    const post = await app.apolloProvider.defaultClient.query({
      query: postQuery,
      variables: { slug: params.slug }
    }).then(({ data }) => data && data.post)

    if (!post) return error({ statusCode: 404, message: 'Not found!!' })
    
    return { post }
  },

Nuxt 1.4.2 is working normally, anyone have the same problem? Another weird thing, on codesanbox, nuxt 2.1.0 still working.

What is expected ?

Shouldn't get error.

What is actually happening?

Getting error.

This bug report is available on Nuxt community (#c145)
@ghost ghost added the cmty:bug-report label Oct 1, 2018
@dohomi
Copy link
Contributor

dohomi commented Oct 1, 2018

@kieusonlam apollo-module is currently not prepared for Nuxt v2 yet. There are currently opened issues with vue-apollo and I'm not sure whats the right way to circumvent the current situation. You can follow #158 where I started to upgrade but I'm kind of stuck currently with SSR compatibility. Beside that I also don't have a Nuxt v2 project in place to run. Please feel free to contribute in the PR or open a PR for just for compatibility reasons for v2

@evseevnn-zzz
Copy link

@kieusonlam Yes, i got same. Do you know reason for that?

@bjunc
Copy link
Contributor

bjunc commented Oct 3, 2018

I ran into this error this morning when attempting to upgrade to Nuxt 2.1. After some investigating, I was able to get it to work by cloning the Apollo response. I typically do this anyway due to how Apollo returns data as read-only, but this one particular page returning the error was one area I wasn't cloning. Here's an example:

Throws error in Nuxt 2.1:

let client = app.apolloProvider.defaultClient
try {
  let { data } = await client.query({ query: USER_QUERY })
  Object.assign(store.state.user, data.user)
} catch (err) {
  // handle error
}

Works in Nuxt 2.1:

Object.assign(store.state.user, _.clone(data.user))

Note: lodash is used here, but there are other ways to "clone" responses worth investigating for your wants/needs.

I haven't yet diagnosed exactly what causes this, but it seems more to do with Nuxt than it does Apollo (and/or vue-apollo). Rather, it seems Nuxt is using the devalue module; which doesn't like symbolic keys (which happened to be returned from Apollo).

I don't know why/where Nuxt is using the devalue module. I also think it's probably wise for Nuxt to catch the error and throw a warning in this case, rather than letting devalue throw the error uncaught.

I would exercise caution if Nuxt has systemic issues with read-only or symbolic keys.

If I find out more about this, I'll post back here.

@aldarund
Copy link
Contributor

aldarund commented Oct 4, 2018

nuxt/nuxt#4046

@aldarund
Copy link
Contributor

aldarund commented Oct 4, 2018

@bjunc warning is coming instead of error. As for symbolic keys - they wasnt serializing before too, they was just silently ignored. Symbol are not really serializable thing..

@bjunc
Copy link
Contributor

bjunc commented Oct 4, 2018

Thanks @aldarund. Also nice that you're printing the symbol keys that couldn't be stringified for debugging.

I looked a little bit more into this, and it turns out Apollo uses a symbol for the ID; which I believe is used for internal caching. That means every apollo response will trigger the warning that you've written unless the developer plucks only the serializable data. Since Apollo also sends responses frozen (read-only), I typically use Lodash's clone function anyway. That clone function (similar to the structured clone algorithm) skips symbols and essentially "unfreezes" the response data.

So I think my suggestion to anyone reading this is to clone the apollo response as now a best practice to not only unfreeze the apollo response data, but avoid the devalue warning (which will also avoid the current error before the error-to-warning PR is merged).

@davision
Copy link

davision commented Oct 5, 2018

I believe this has no connection with apollo. Using this code throws the same error:

  async asyncData({params}) {
    const fileContent = await import(`~/static/content/${params.slug}.md`)

    return {
      content: fileContent,
    }
  },

throws:

✖ error NuxtServerError: Cannot stringify POJOs with symbolic keys
  at walk (/Users/davidlicen/Documents/Projects/0xcert/landing-www/node_modules/devalue/dist/devalue.umd.js:47:31)
  at /Users/davidlicen/Documents/Projects/0xcert/landing-www/node_modules/devalue/dist/devalue.umd.js:49:72
  at Array.forEach (<anonymous>)
  at walk (/Users/davidlicen/Documents/Projects/0xcert/landing-www/node_modules/devalue/dist/devalue.umd.js:49:40)
  at Array.forEach (<anonymous>)
  at walk (/Users/davidlicen/Documents/Projects/0xcert/landing-www/node_modules/devalue/dist/devalue.umd.js:33:27)
  at /Users/davidlicen/Documents/Projects/0xcert/landing-www/node_modules/devalue/dist/devalue.umd.js:49:72
  at Array.forEach (<anonymous>)
  at walk (/Users/davidlicen/Documents/Projects/0xcert/landing-www/node_modules/devalue/dist/devalue.umd.js:49:40)
  at devalue (/Users/davidlicen/Documents/Projects/0xcert/landing-www/node_modules/devalue/dist/devalue.umd.js:53:5)
  at Renderer.renderRoute (/Users/davidlicen/Documents/Projects/0xcert/landing-www/node_modules/nuxt/dist/nuxt.js:2042:50)
  at <anonymous>

Using Nuxt 2.1

@bjunc
Copy link
Contributor

bjunc commented Oct 5, 2018

@davision per above, this error has more to do with the devalue module not like Symbol keys; which Apollo happens to use. I don't know what is returned from your example, but there's likely a Symbol in there. You can check by:

Object.getOwnPropertySymbols(fileContent)

@dohomi
Copy link
Contributor

dohomi commented Oct 6, 2018

@bjunc I tried your above code but for me the symbols are not removed through lodash.clone:

        const article = _clone(data) // this is from a query response of apollo
        console.log('article:', Object.getOwnPropertySymbols(article)) // => article: [ Symbol(id) ]

Any idea how to remove the symbols?

@bjunc
Copy link
Contributor

bjunc commented Oct 7, 2018

@dohomi, I believe the above should work. However, _.clone() is shallow, so if your article has nested objects, they too will have symbols for the ID. Did you try _.cloneDeep()?

@dohomi
Copy link
Contributor

dohomi commented Oct 8, 2018

@bjunc I realized that somehow lodash.deepclone did not remove the symbols. I changed to clone-deep package and now it works as expected, thanks for the hint.

@AndrewBogdanovTSS
Copy link
Contributor

AndrewBogdanovTSS commented Oct 8, 2018

@dohomi I tried it with v4.0.0-rc.2.2 but still got this error

@dohomi
Copy link
Contributor

dohomi commented Oct 8, 2018

@AndrewBogdanovTSS where do you see this error? As @bjunc correctly stated, you need to clone/cloneDeep your response inside of asyncData to remove the symbolic keys. This worked for me. I am using https://www.npmjs.com/package/clone-deep to make this work

@AndrewBogdanovTSS
Copy link
Contributor

@dohomi yeah, after I switched to deep-clone in my code it started to work as expected. Thank you.

@kieusonlam
Copy link
Collaborator Author

Closed. We can use this solution #163 (comment) until this PR nuxt/nuxt#4046 be merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants