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
+
+-
+-
+-