diff --git a/docs/headingsDetached.tsx b/docs/headingsDetached.tsx index ab7c10dfa91..f02fae6ea7f 100644 --- a/docs/headingsDetached.tsx +++ b/docs/headingsDetached.tsx @@ -354,7 +354,7 @@ const headingsDetached = [ { title: 'Abort', url: '/abort', - sectionTitles: ['`throw redirect()` VS `throw render()`'] + sectionTitles: ['`throw redirect()` VS `throw render()` VS `navigate()`'] }, { title: 'Custom Exports/Hooks', diff --git a/docs/pages/abort/+Page.mdx b/docs/pages/abort/+Page.mdx index 03fe6adc9a2..ca11b4d379e 100644 --- a/docs/pages/abort/+Page.mdx +++ b/docs/pages/abort/+Page.mdx @@ -1,24 +1,51 @@ import { Link } from '@brillout/docpress' -By using throw render()}> or throw redirect()}> you abort the rendering of the current page and render something else instead. +You can use `throw render()` or `throw redirect()` in order to abort rendering the current page and render something else instead. -## `throw redirect()` VS `throw render()` -While `throw redirect()` changes the URL, `throw render()` preserves it: - - If a user goes to `/admin` and `throw redirect('/login')` is called, then the user will see the new URL `/login` in the browser's address bar. - - If a user goes to `/admin` and `throw render('/login')` is called, then the user keeps seeing the same URL `/admin` in the browser's address bar. +## `throw redirect()` VS `throw render()` VS `navigate()` + +**`throw redirect()` VS `throw render()`** + +While `throw redirect()` changes the URL, `throw render()` preserves it: + - If a user goes to `/admin` and `throw redirect('/login')` is called, then the `/login` page is rendered and the user sees a new URL `/login` in the address bar of his browser. + - If a user goes to `/admin` and `throw render('/login')` is called, then the `/login` page is rendered but the user keeps seeing the same URL `/admin` in the address bar of his browser (even though the `/login` page is rendered). + +> We usually recommend using `throw render()` instead of `throw redirect()` as it preserves the URL and, therefore, the user's intention. We further explain this technique at . + +**`throw redirect()` VS `navigate()`** + +Difference between `throw redirect()` and `navigate()`: + - `navigate()` only works on the client-side and shouldn't be called during the rendering of a page. + - `throw redirect()` works on both client- and server-side but only works during the rendering a page. + +In a nuthsell: if you want to abort the rendering of a page then use `throw redirect()`, otherwise use `navigate()`. + +For example: + - For redirecting the user upon a form submit action, use `navigate()`. (Since the page is already rendered and thus `throw redirect()` doesn't make sense as there is no pending page rendering to abort.) + - For protecting a page from unprivileged access, such as a normal user trying to access an admin page, use `throw redirect()` in order to abort (on both server- and client-side) the rendering of the admin page and redirect the user to another page instead (for example the login page). -In general, we recommend using `throw render('/login')` instead of `throw redirect('/login')` as it preserves the URL and, therefore, the user's intention. We further explain this techniue at . ## Debug If `throw redirect()` or `throw render()` doesn't work: - - **Make sure `throw redirect()` / `throw render()` isn't swallowed.** - In developement, check your server logs for the following log. If this log is missing then this means that Vike didn't receive the `throw redirect()` / `throw render()` exception: some other code is catching and swallowing it. + - **Make sure `throw redirect()` / `throw render()` isn't intercepted.** + In developement, check your server logs for the following log. If the log is missing then it means that Vike didn't catch the `throw redirect()` / `throw render()` exception: some other code is intercepting it and thus prevents Vike from catching it. ``` 10:00:00 AM [vike][request(42)] throw redirect('/some-url') intercepted while rendering /some-other-url ``` + > Most notably, using `throw redirect()` / `throw render()` inside a UI component usually doesn't work because most UI frameworks will intercept the execption, and thus Vike won't be able to catch it. Instead, consider using `throw redirect()` / `throw render()` in a Vike hook such as `guard()` or `data()`, or use `navigate()`. + - **Make sure to use `throw redirect()` / `throw render()` within a Vike hook.** + If you use `throw redirect()` / `throw render()` outside of Vike hooks, for example in some server middleware code, then Vike won't be able to intercept it. + If `throw redirect()` doesn't work: - **Make sure to add `pageContext.httpResponse.headers` to the HTTP response.** If you've embedded Vike into your server using renderPage()} href="/renderPage" />, then insepct whether `pageContext.httpResponse.headers` contains the `Location` header and double check that you're correctly adding all the headers defined by `pageContext.httpResponse.headers` to the HTTP response. + + +## See also + + - + - + - diff --git a/docs/pages/navigate/+Page.mdx b/docs/pages/navigate/+Page.mdx index 58b4c603277..af5224a15dd 100644 --- a/docs/pages/navigate/+Page.mdx +++ b/docs/pages/navigate/+Page.mdx @@ -26,7 +26,7 @@ async function onSubmit() { } ``` -> If you want to redirect while rendering a page (e.g. redirect non-authenticated users to a login page), then use instead. +> If you want to redirect the user while rendering a page (e.g. redirect non-authenticated users to a login page), then use `throw redirect()` instead. See . > If you want to navigate back, then use [`window.history.back()`](https://developer.mozilla.org/en-US/docs/Web/API/History/back) instead. @@ -76,4 +76,6 @@ If you don't use a and if you use +- +- +- diff --git a/docs/pages/redirect/+Page.mdx b/docs/pages/redirect/+Page.mdx index b3ff6172d3b..0c5954effd1 100644 --- a/docs/pages/redirect/+Page.mdx +++ b/docs/pages/redirect/+Page.mdx @@ -1,10 +1,5 @@ import { Link } from '@brillout/docpress' -See also: - - - - - - - ```ts // Redirect the user to another URL redirect(url: `/${string}` | `https://${string}` | `http://${string}`) @@ -20,13 +15,26 @@ function onSomeHook() { } ``` -> `throw redirect()` makes temporary redirections (HTTP status code `302`). For permanent redirections (HTTP status code `301`), you can set or pass a second argument `throw redirect('/some-url', 301)`. +> `throw redirect()` is about *aborting* a page from being rendered and redirecting to the user to another page instead. Use `navigate()` if you want to redirect *after* the page is already rendered. See . -While it's most commonly used with [`guard()`](/guard) or [`data()`](/data) you can use it with any hook. +> `throw redirect()` makes temporary redirections (HTTP status code `302`). For permanent redirections (HTTP status code `301`), use the `redirects` setting or pass a second argument `throw redirect('/some-url', 301)`. Common use cases: - Authentication and authorization, see . - Data fetching error handling, see . -If `throw redirect()` doesn't work, see . +While it's most commonly used with [`guard()`](/guard) or [`data()`](/data) you can use it with any hook. + +> For improved DX, consider using `throw render()` instead of `throw redirect()`. See . + +If `throw redirect()` doesn't work, see and . + + +## See also + +- +- +- +- +- diff --git a/docs/pages/render/+Page.mdx b/docs/pages/render/+Page.mdx index 2790844680c..4979640e058 100644 --- a/docs/pages/render/+Page.mdx +++ b/docs/pages/render/+Page.mdx @@ -1,9 +1,6 @@ import { Link } from '@brillout/docpress' -See also: - - - - - - +`throw render()` is like `throw redirect()` but preserves the URL, see . ```ts // Render the error page @@ -12,8 +9,6 @@ render(abortStatusCode: 401 | 403 | 404 | 429 | 500 | 503, abortReason?: unknown render(url: `/${string}`, abortReason?: unknown) ``` -> If you use TypeScript, you can define the `abortReason` type by using the global interface `Vike.PageContext`, see . - ```js import { render } from 'vike/abort' @@ -36,6 +31,7 @@ function onSomeHook() { - [`500` Internal Server Error](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500) - App has a bug. - [`503` Service Unavailable](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503) - Server is overloaded and/or a third-party API isn't responding. - The `abortReason` and `abortStatusCode` arguments are made available at `pageContext.abortReason` and `pageContext.abortStatusCode` which is useful for enabling the error page to show a useful error message to the user, see . + > If you use TypeScript, you can define the `abortReason` type by using the global interface `Vike.PageContext`, see . While it's most commonly used with [`guard()`](/guard) or [`data()`](/data) you can use it with any hook. @@ -45,3 +41,10 @@ Common use cases: - Data fetching error handling, see . If `throw render()` doesn't work, see . + + +## See also + +- +- +-