A
Alokai•2y ago
___anj___

How to detect if a page has an error inside the layout

Inside the default layout I need to detect if there is an error page displayed (like for example a 404 page). How should I do this? I've tried doing this by accessing app.context._errored but this value is not refreshed after a client side navigation, so if we navigate from page with an error to a working page the value of this field remains the same. Is there an out of the box solution for that or we need to develop custom solution? And if we need to develop custom solution how should one go about it? Should we create a composable that will hold the error state and somehow update it when error layout is invoked? What would be the proper lifecycle hoot to update such variable?
19 Replies
rohrig
rohrig•2y ago
hi, @AnJ 👋 Do you need access to the specific error, or just to know you're on the error page?
___anj___
___anj___•2y ago
Hi, @rohrig . I need to know if I'm on the error page, no matter what the error is.
rohrig
rohrig•2y ago
My first instinct would be to useRoute, perhaps in a middleware, and check if the 404 page, or any other error page, matches the current route. Would that work for you?
___anj___
___anj___•2y ago
Maybe I'm not fully understanding your proposal, but I don't think that would work. As far as I know we don't have something like a dedicated error route. So we can for example enter a non-existent URL and we will get useRoute response like this:
___anj___
___anj___•2y ago
And in case we will enter an existing URL that matches with a URL inside router configuration, but for some reason there is an error thrown (inside onSSR hook), then we get just this particular route, like for example home page route. I'm not sure how we could check if there is an error in that. @rohrig I was thinking about a small composable like this:
import { sharedRef } from '@vue-storefront/core';
import { computed } from '@nuxtjs/composition-api';

export default () => {
const isErrored = sharedRef(false, 'isErrored');

const setError = (error: boolean) => {
isErrored.value = error;
};

return {
isErrored: computed(() => isErrored.value),
setError,
};
};
import { sharedRef } from '@vue-storefront/core';
import { computed } from '@nuxtjs/composition-api';

export default () => {
const isErrored = sharedRef(false, 'isErrored');

const setError = (error: boolean) => {
isErrored.value = error;
};

return {
isErrored: computed(() => isErrored.value),
setError,
};
};
That we could use to store our custom state, and then use it inside our error layout. So that when error layout is being generated we will set isErrored to true. But admittedly this feels kinda wonky and I'm not sure if this is a proper path.
rohrig
rohrig•2y ago
@AnJ you're right, my first instinct was not correct. 😄 Have you tested if you're proposed solution works?
___anj___
___anj___•2y ago
Almost. I'm having trouble with picking correct hook in which I should call the setError method. First I tried putting it inside onSSR like this: Error layout (error.vue):
onSSR(async () => {
setError(true);
// ...
});
onSSR(async () => {
setError(true);
// ...
});
Main layout (default.vue):
onSSR(async () => {
setError(false);
// ...
});
onSSR(async () => {
setError(false);
// ...
});
For server side it works fine. If there is no error then only setError(false) is called from the main layout. And if there is an error on the page then setError is called twice, first from default layout with false, then from error layout with true. And it works as expected. The problem arises when I'm navigating on the client side. The setError inside the main layout is not called at all when doing client side navigation. So if I open a page with an error there is a setError(true) call. And then when I navigate to a page without an error, the value is not updated and it is still isErrored = true. I don't know how to get this to work. What hook should I use so that setError will be called both for server side and for client side navigation?
rohrig
rohrig•2y ago
have you tried calling it in both onSSR and onMounted?
___anj___
___anj___•2y ago
Yes. Then we get a race condition where on SSR stage we get something like this:
1. default.vue -> onSSR() -> setError(false)
2. error.vue -> onSSR() -> setError(true)
1. default.vue -> onSSR() -> setError(false)
2. error.vue -> onSSR() -> setError(true)
and then after that on the client side we get the reverse
1. error.vue -> onMounted() -> setError(true)
2. default.vue -> onMounted() -> setError(false)
1. error.vue -> onMounted() -> setError(true)
2. default.vue -> onMounted() -> setError(false)
In consequence the final value is isErrored = false
rohrig
rohrig•2y ago
I see 🤔 , let me see what I can find. I'll get back to you. If you solve it in the meantime, please let me know. 🙂
___anj___
___anj___•2y ago
Thank you 🙂
rohrig
rohrig•2y ago
I'm looking into this. What integration and version are you on? @AnJ The reason I ask is, when I get an error, out of the box it's using the ~/layouts/error.vue. Not the default layout
___anj___
___anj___•2y ago
Core integration is this: "@vue-storefront/core": "^2.7.1", When we get an error we get a default layout with error layout nested inside
rohrig
rohrig•2y ago
can you paste in your package.json please?
rohrig
rohrig•2y ago
I'm looking at https://nuxtjs.org/docs/concepts/views/#error-page. Could you elaborate on your end goal, Other than just detecting errors in the default layout, what is it you're trying to achieve?
Nuxt
Views
The Views section describes all you need to know to configure data and views for a specific route in your Nuxt Application. Views consist of an app template, a layout, and the actual page.
Want results from more Discord servers?
Add your server