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
allow manually redirecting to 404 route within a dynamic slug #13788
Comments
|
If I have logic in setup inside [slug].vue where I call useFetch and the api returns 404, I would like to redirect to the /404 route which is not possible now. |
@danielroe Example: I have a bike shop. A customer accesses the route: http://bike.com => index.vue. The customer wants to view the bike categories http://bike.com/blue-bikes => [slug].vue. The customer selects one of the bikes from the category, http://bike.com/best-blue-bike.html => [slug].html.vue. Everything works great, but how do I catch the condition where I want to redirect to a 404 page? |
Are you saying this used to work? Would you provide an example of what you're wanting to do? (I'm asking as this is a key behaviour and we need to make this as straightforward as we can, so we either need to improve DX or document some examples.) |
I am positive the broad idea of this issue is to ask "how to handle 404 on dynamic path". const $route = useRoute()
const { data } = await useAsyncData(`product:${$route.params.id}`, () => $fetch(`/api/products/${$route.params.id}`))
// TODO: Display proper 404 when accessing unknown product id
// Requirements:
// - Using default error page - big "404" with small "Page not found: /product/42" - just like native nuxt 404
// - On all types of navigation:
// a) Home -> Product/42 (client)
// b) Home -> Product/42 -> Home -> Product/42 (client + cache)
// c) Product/42 (server)
// d) Product/42 -> Home -> Product/42 (server into client + cache)
// - Proper status code and status message when SSR (404, Not Found) There is currently no documentation on how to properly handle API's 404 response in the docs. From my experience it is also extremely hard, as all of the 4 navigation types listed in comments above require different logic each. Here is the repo reproduction in case you want to bootstrap the project: data-fetching |
Thanks for that link @Aareksio. I've submitted a related PR to fix an issue, add some basic docs and improve DX (by avoiding import of |
You got around checking for 404 in pretty clever way @danielroe! This surely answers on how to display 404 when the server returns an error, but we may need different handling for different kind of errors, eg. 5xx, 403, 429 all should stay on the path and return specific status codes. In all cases, the I think your solution answers this particular issue, as the OP didn't seem to be concerned with proper status code. |
@danielroe Even with your fix, when using SSR the backend still throws internal an error (and flashes it until the hidration takes over):
It's visible in the logs of the example you provided, but here's a minimal example nontheless: https://stackblitz.com/edit/nuxt-starter-nlacpe nuxt-3-rc3-throwError-ssr-issue.mp4The error is thrown whenever |
@danielroe the throwError seems to be marked as deprecated now. Swapping for throw createError seems to output fails in the server console "[nitro] [dev] [unhandledRejection] Error: nuxt instance unavailable
|
Seems working fine on latest RC8 to me, without any workarounds: https://stackblitz.com/edit/nuxt-starter-fbuud2. Let me know if not and I'll reopen. |
@danielroe indeed it works on the initial "faulty" load. It seems to me it is failing if I am doing some clientside navigation to something faulty though. Is just a limitation to be aware of, or should it be working? |
We deliberately don't throw a full page error in this case by default (so you can handle it within the UI with more granular error handlers). But if you want the full error page, you can add |
I'm having a related problem rendering a 404 error: <!-- test404.vue -->
<template>
<div>Content: {{ data.id }}</div>
</template>
<script lang="ts">
export default defineComponent({
async setup() {
const { data, error } = await useAsyncData<{ id: number }>(async () => {
// URL returns 404, causing fetch to throw an error
return await $fetch('https://run.mocky.io/v3/b764d683-f7cd-4128-9de0-077d891d3886')
})
if (error.value) {
console.log('error detected')
throw createError({
statusCode: 404,
fatal: true,
})
}
return { data }
},
})
</script> The console shows:
So, instead of 404, a 500 error is rendered, because the template is trying to access a property of I'd like to avoid to wrap my whole template into a |
Minimal reproduction for the above, using script setup for readability: https://stackblitz.com/edit/github-5jhffm |
@danielroe I am afraid the error handling of API responses is still not perfect. This time no shortcuts, need to handle both 404 and 500 properly (read error value): https://stackblitz.com/edit/github-cmeky2?file=pages/movie/[id].vue |
@Aareksio This seems to work for me. As far as retrying requests in certain conditions, you can provide an const { data: movie, error } = await useAsyncData(`movie:${$route.params.id}`, () => $fetch(`/api/movie/${$route.params.id}`));
if (error.value && error.value.response) {
throw createError({
fatal: true,
statusCode: error.value.response.status
})
} Please feel free to open a feature request if you think something is missing. Though do note that this overlaps slightly with #12885, which I think is a valid issue we need to improve. |
@danielroe https://yko.im/1_it.mp4 Case b: Home -> Movie/[id] -> Home -> Movie/[id] (client + cache) Breaks after repetitive visit after client request. By "retry request" I did not meant retry directly after fail. On repetitive view data is loaded from cache, meaning the request never hits the server. Imagine the user gets 419 (rate limit) when browsing user profiles, we display proper error message. They proceed to browse other, not limited, parts of the app. After 30 minutes they decide to check the profile again. On server the rate limit is long gone, but client do not even hit the API and instead display cached error (assuming the issue from video gets fixed). |
Agreed - I think it does make sense to add more caching strategies. (Though note that you can also implement your own by setting |
Created two issues to follow:
Feel free to open a new one if you think there's another one to track. |
Should I open a separate issue for that? Edit: Created #14695. |
Environment
Reproduction
https://stackblitz.com/edit/github-yyumyt?file=pages/404.vue
Describe the bug
I have defined three pages (routes):
car.vue
[slug].vue
404.vue
If I go to
http://.../hi
=> it loads[slug].vue
=> OKIf I go to
http://.../car
=> it loadscar.vue
=> OKIf I go to
http://.../404
=> it loads[slug].vue
=> FAILAdditional context
No response
Logs
No response
The text was updated successfully, but these errors were encountered: