I want to call the context.error({...}) to show the Nuxt's error page when a query failed (Item not found, etc.).
In asyncData(context) {...}, we can easily do that as context is always given.
However inside vue-apollo's smart queries, I can't find a way to access the error()
I just found that I can access the error function via this.$root (even on server-side).
Is it the right (or stable) way to use this.$root on server-side?
apollo: {
entry: {
query: ENTRY_QUERY,
error() { // or result(...)
this.$root.error({'statusCode': 404, 'message': 'OK'})
},
variables: {
// ...
},
prefetch: true,
}
},
Edit: This doesn't work in SSR.
Hi @ciscorn
I think there are several ways of doing it. I prefer to redirect the user inside of the result hook. But your way is also a possible way of doing it
@dohomi I noticed that my code above (and your suggestion) doesn't work in SSR because the result and error handlers are evaluated after SSR has done.
@ciscorn yes we discovered this. Its something you can track inside of vue-apollo it has not necessary something todo with this package.
Try wrap your code in
result({data}){
this.$nextTick(() => {
// here you can set context to your component
})
}
Sorry I think I misread your question. Maybe @Akryum has a good idea how to solve this, I always wait for the result and then redirect the user to error pages
@dohomi Thanks. I think something (such as prefetchResult handler) should be implemented on vue-apollo to serve real 404/302 pages in SSR.
@ciscorn please open an issue inside of vue-apollo package. This package just supersets the usage of vue-apollo and will not add any features to extend vue-apollo
(Please ignore if this is irreverent)
I created a modified version of apollo-module just for testing.
https://github.com/ciscorn/nuxtjs-apollo-explicit-module
This solves the error/redirect problem and a (potential) concurrency issue without any modifications both to Nuxt and vue-apollo. (However it introduces breaking changes.)
Please read a brief explanation in my README.md.
@ciscorn what happens if you use:
async fetch(context) {
const result = await contxt.app.apolloProvider.defaultClient.query(YOUR_QUERY_OBJECT)
// You can call context.error (or redirect) based on the result
},
//! without any apollo...
with this package? I do this on some parts and had no issues so far.
@dohomi @Akryum @Atinux
(I'm sorry if I'm misunderstanding something but...)
Nuxt.js has a built-in functionality to return 404/403/302/301/etc HTTP responses with context.error(...) and context.redirect(...). However with the original @nuxtjs/apollo, prefetching is performed after the Nuxt has finished checking the error/redirect flags, so the Nuxt's context.error doesn't work at the time apollo-module's prefetching has done.
(I think #35 is a bit related to the same problem.)
With my modified version, I can return "real 404/403" HTTP responses to clients based on query results with the Nuxt's built-in functionality. I think it's important for SSR and SEO. Redirecting to /404 page or something are not so beautiful and it just returns 200. We should be able to return error and redirect HTTP responses to clients and search engine crawlers without URL changes. (Nuxt.js itself kindly supports this.)
With my modified version, I can do:
async fetch({app, error}) {
const prefetchResult = await app.apolloPrefetch(this)
if (!prefetchResult.article.data.article) {
error({statusCode: 404, message: "Item Not Found"})
}
},
And then clients receive 404 responses:

@ciscorn ok I understand now better. @Akryum what do you think about this approach?
Any news on this? Really want to use this implementation!
@kavalcante @ciscorn haven't had this implementation on my radar yet. You can gain same result with following code:
async asyncData({error, app, params}){
const article = await app.apolloProvider.defaultClient.query({
query: `someGql`,
variables:{id: params.id}
}).then(({data}) => data && data.Article)
if(!article){
return error({statusCode: 404, message: 'Not found'})
}
return {article}
}
Is there any reason why not using asncData directly, you would write actually less code to receive the same result. Setting up a fetch method is slightly redundant in my eyes. I'm not sure if its straight forward to decouple the query call and add the fetch statement to it. @Akryum I'd still be interested if you have any opinion as you have better knowledge in the vue-apollo client.
Looks a good implementation @dohomi, thanks for the example!
@dohomi One major reason to do ciscorn's implementation is that with your solution I have to do a query. Given this basic example of routing :
Pages
/product
_id.vue
The query is always sent before I can validate or asyncData (fetch isn't even invoked SSR). All I'd like to do is if there is no id param provided then re-route to the home page or something, but if apollo is added onto the component it does not work. If I have no apollo section on my vue component it works normally. I think the bug and issue belongs here because validate and errors are a Nuxt feature, not a Vue feature.
@JRobber sorry I am not sure if I follow correctly.. We are talking about query or fetching data from any component right? As Nuxt provides asnycData and you would not provide an _id param you can make a redirect in your asyncData before you would query your data:
asyncData({error, app, params, redirect}){
if(!params.id){
return redirect('/anywhere')
}
const article = await app.apolloProvider.defaultClient.query({
query: `someGql`,
variables:{id: params.id}
}).then(({data}) => data && data.Article)
if(!article){
return error({statusCode: 404, message: 'Not found'})
}
return {article}
}
I'm not sure if I understand your concern correctly though..
My solution is a kind of dirty hack to avoid using beforeNuxtRender.
It would be the best if we can set up a hook here.
As version 4 follows now a different approach I will close this issue. Most likely it does not solve your issue but maybe the best way would be to run a separate module for it.
@dohomi, you mention a new approach as of version 4, but I'm not sure where to find more information on that approach. Would you mind pointing me towards some docs?
Thanks for all your work on @nuxtjs/apollo!
@aaronransley whats the exact issue you are facing?
I see this issue is closed, does that mean smart queries are officially discouraged in favor of asyncData?
Right now I don't see a way to set the HTTP status code from the server side using a smart query, so instead we must use context.app.apolloProvider.defaultClient.query; definitely less elegant
+1 Definitely would like to see this in the smart query as well.
@aaronransley when using asyncData, the the data will not update with mutations(/changes to cache).
Most helpful comment
@kavalcante @ciscorn haven't had this implementation on my radar yet. You can gain same result with following code:
Is there any reason why not using
asncDatadirectly, you would write actually less code to receive the same result. Setting up a fetch method is slightly redundant in my eyes. I'm not sure if its straight forward to decouple the query call and add the fetch statement to it. @Akryum I'd still be interested if you have any opinion as you have better knowledge in thevue-apolloclient.