Skip to content

Commit

Permalink
feat(eslint-plugin-next): rename no-redirect-in-try-catch to `no-re…
Browse files Browse the repository at this point in the history
…direct-in-try-catch-without-rethrow` and update docs
  • Loading branch information
piotrski committed Sep 4, 2024
1 parent 91c8508 commit 6362a6f
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,30 +93,30 @@ Next.js provides an ESLint plugin, [`eslint-plugin-next`](https://www.npmjs.com/

<Check size={18} /> Enabled in the recommended configuration

| | Rule | Description |
| :-----------------: | ------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| <Check size={18} /> | [@next/next/google-font-display](/docs/messages/google-font-display) | Enforce font-display behavior with Google Fonts. |
| <Check size={18} /> | [@next/next/google-font-preconnect](/docs/messages/google-font-preconnect) | Ensure `preconnect` is used with Google Fonts. |
| <Check size={18} /> | [@next/next/inline-script-id](/docs/messages/inline-script-id) | Enforce `id` attribute on `next/script` components with inline content. |
| <Check size={18} /> | [@next/next/next-script-for-ga](/docs/messages/next-script-for-ga) | Prefer `next/script` component when using the inline script for Google Analytics. |
| <Check size={18} /> | [@next/next/no-assign-module-variable](/docs/messages/no-assign-module-variable) | Prevent assignment to the `module` variable. |
| <Check size={18} /> | [@next/next/no-async-client-component](/docs/messages/no-async-client-component) | Prevent client components from being async functions. |
| <Check size={18} /> | [@next/next/no-before-interactive-script-outside-document](/docs/messages/no-before-interactive-script-outside-document) | Prevent usage of `next/script`'s `beforeInteractive` strategy outside of `pages/_document.js`. |
| <Check size={18} /> | [@next/next/no-css-tags](/docs/messages/no-css-tags) | Prevent manual stylesheet tags. |
| <Check size={18} /> | [@next/next/no-document-import-in-page](/docs/messages/no-document-import-in-page) | Prevent importing `next/document` outside of `pages/_document.js`. |
| <Check size={18} /> | [@next/next/no-duplicate-head](/docs/messages/no-duplicate-head) | Prevent duplicate usage of `<Head>` in `pages/_document.js`. |
| <Check size={18} /> | [@next/next/no-head-element](/docs/messages/no-head-element) | Prevent usage of `<head>` element. |
| <Check size={18} /> | [@next/next/no-head-import-in-document](/docs/messages/no-head-import-in-document) | Prevent usage of `next/head` in `pages/_document.js`. |
| <Check size={18} /> | [@next/next/no-html-link-for-pages](/docs/messages/no-html-link-for-pages) | Prevent usage of `<a>` elements to navigate to internal Next.js pages. |
| <Check size={18} /> | [@next/next/no-img-element](/docs/messages/no-img-element) | Prevent usage of `<img>` element due to slower LCP and higher bandwidth. |
| <Check size={18} /> | [@next/next/no-page-custom-font](/docs/messages/no-page-custom-font) | Prevent page-only custom fonts. |
| <Check size={18} /> | [@next/next/no-script-component-in-head](/docs/messages/no-script-component-in-head) | Prevent usage of `next/script` in `next/head` component. |
| <Check size={18} /> | [@next/next/no-styled-jsx-in-document](/docs/messages/no-styled-jsx-in-document) | Prevent usage of `styled-jsx` in `pages/_document.js`. |
| <Check size={18} /> | [@next/next/no-sync-scripts](/docs/messages/no-sync-scripts) | Prevent synchronous scripts. |
| <Check size={18} /> | [@next/next/no-title-in-document-head](/docs/messages/no-title-in-document-head) | Prevent usage of `<title>` with `Head` component from `next/document`. |
| <Check size={18} /> | @next/next/no-typos | Prevent common typos in [Next.js's data fetching functions](/docs/pages/building-your-application/data-fetching) |
| <Check size={18} /> | [@next/next/no-unwanted-polyfillio](/docs/messages/no-unwanted-polyfillio) | Prevent duplicate polyfills from Polyfill.io. |
| <Check size={18} /> | [@next/next/no-redirect-in-try-catch](/docs/messages/no-redirect-in-try-catch) | Prevent usage of `redirect` in try-catch block. |
| | Rule | Description |
| :-----------------: | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| <Check size={18} /> | [@next/next/google-font-display](/docs/messages/google-font-display) | Enforce font-display behavior with Google Fonts. |
| <Check size={18} /> | [@next/next/google-font-preconnect](/docs/messages/google-font-preconnect) | Ensure `preconnect` is used with Google Fonts. |
| <Check size={18} /> | [@next/next/inline-script-id](/docs/messages/inline-script-id) | Enforce `id` attribute on `next/script` components with inline content. |
| <Check size={18} /> | [@next/next/next-script-for-ga](/docs/messages/next-script-for-ga) | Prefer `next/script` component when using the inline script for Google Analytics. |
| <Check size={18} /> | [@next/next/no-assign-module-variable](/docs/messages/no-assign-module-variable) | Prevent assignment to the `module` variable. |
| <Check size={18} /> | [@next/next/no-async-client-component](/docs/messages/no-async-client-component) | Prevent client components from being async functions. |
| <Check size={18} /> | [@next/next/no-before-interactive-script-outside-document](/docs/messages/no-before-interactive-script-outside-document) | Prevent usage of `next/script`'s `beforeInteractive` strategy outside of `pages/_document.js`. |
| <Check size={18} /> | [@next/next/no-css-tags](/docs/messages/no-css-tags) | Prevent manual stylesheet tags. |
| <Check size={18} /> | [@next/next/no-document-import-in-page](/docs/messages/no-document-import-in-page) | Prevent importing `next/document` outside of `pages/_document.js`. |
| <Check size={18} /> | [@next/next/no-duplicate-head](/docs/messages/no-duplicate-head) | Prevent duplicate usage of `<Head>` in `pages/_document.js`. |
| <Check size={18} /> | [@next/next/no-head-element](/docs/messages/no-head-element) | Prevent usage of `<head>` element. |
| <Check size={18} /> | [@next/next/no-head-import-in-document](/docs/messages/no-head-import-in-document) | Prevent usage of `next/head` in `pages/_document.js`. |
| <Check size={18} /> | [@next/next/no-html-link-for-pages](/docs/messages/no-html-link-for-pages) | Prevent usage of `<a>` elements to navigate to internal Next.js pages. |
| <Check size={18} /> | [@next/next/no-img-element](/docs/messages/no-img-element) | Prevent usage of `<img>` element due to slower LCP and higher bandwidth. |
| <Check size={18} /> | [@next/next/no-page-custom-font](/docs/messages/no-page-custom-font) | Prevent page-only custom fonts. |
| <Check size={18} /> | [@next/next/no-script-component-in-head](/docs/messages/no-script-component-in-head) | Prevent usage of `next/script` in `next/head` component. |
| <Check size={18} /> | [@next/next/no-styled-jsx-in-document](/docs/messages/no-styled-jsx-in-document) | Prevent usage of `styled-jsx` in `pages/_document.js`. |
| <Check size={18} /> | [@next/next/no-sync-scripts](/docs/messages/no-sync-scripts) | Prevent synchronous scripts. |
| <Check size={18} /> | [@next/next/no-title-in-document-head](/docs/messages/no-title-in-document-head) | Prevent usage of `<title>` with `Head` component from `next/document`. |
| <Check size={18} /> | @next/next/no-typos | Prevent common typos in [Next.js's data fetching functions](/docs/pages/building-your-application/data-fetching) |
| <Check size={18} /> | [@next/next/no-unwanted-polyfillio](/docs/messages/no-unwanted-polyfillio) | Prevent duplicate polyfills from Polyfill.io. |
| <Check size={18} /> | [@next/next/no-redirect-in-try-catch-without-rethrow](/docs/messages/no-redirect-in-try-catch-without-rethrow) | Ensure that when using `redirect` within a try-catch block, the catch block must start with a call to `unstable_rethrow` to ensure proper error propagation. |

If you already have ESLint configured in your application, we recommend extending from this plugin directly instead of including `eslint-config-next` unless a few conditions are met. Refer to the [Recommended Plugin Ruleset](#recommended-plugin-ruleset) to learn more.

Expand Down
45 changes: 45 additions & 0 deletions errors/no-redirect-in-try-catch-without-rethrow.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
title: No Redirect in Try-Catch Without Rethrow
---

> Ensure that when using `redirect` within a try-catch block, the catch block must start with a call to `unstable_rethrow` to ensure proper error propagation.
## Why This Error Occurred

You attempted to use the `redirect` function within a try-catch block without rethrowing the error using `unstable_rethrow`. When `redirect` is called, it throws a `NEXT_REDIRECT` error internally. If this error is caught without being rethrown, it prevents the redirect from executing as intended and suppresses the error handling.

## Possible Ways to Fix It

To ensure proper error handling and that the redirect can proceed as intended, the catch block should start with a call to `unstable_rethrow`. This ensures that Next.js's internal error handling is respected and that the redirect is properly executed.

If you need to handle other errors, you can still do so after the `unstable_rethrow` call.

## Example

### Incorrect Usage:

```javascript
try {
// some code that might throw an error
redirect('/some-path')
} catch (error) {
// handle error
}
```

### Correct Usage:

```javascript
try {
// some code that might throw an error
redirect('/some-path')
} catch (error) {
unstable_rethrow(error)
// handle other errors if necessary
}
```

## Useful Links

- [Next.js Redirect Documentation](/docs/app/building-your-application/routing/redirecting#redirect-function)
- [Next.js Error Handling](/docs/app/building-your-application/routing/error-handling)
43 changes: 0 additions & 43 deletions errors/no-redirect-in-try-catch.mdx

This file was deleted.

4 changes: 2 additions & 2 deletions packages/eslint-plugin-next/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module.exports = {
'no-title-in-document-head': require('./rules/no-title-in-document-head'),
'no-typos': require('./rules/no-typos'),
'no-unwanted-polyfillio': require('./rules/no-unwanted-polyfillio'),
'no-redirect-in-try-catch': require('./rules/no-redirect-in-try-catch'),
'no-redirect-in-try-catch-without-rethrow': require('./rules/no-redirect-in-try-catch-without-rethrow'),
},
configs: {
recommended: {
Expand Down Expand Up @@ -50,7 +50,7 @@ module.exports = {
'@next/next/no-duplicate-head': 'error',
'@next/next/no-head-import-in-document': 'error',
'@next/next/no-script-component-in-head': 'error',
'@next/next/no-redirect-in-try-catch': 'error',
'@next/next/no-redirect-in-try-catch-without-rethrow': 'error',
},
},
'core-web-vitals': {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { defineRule } from '../utils/define-rule'
import type { Node, BlockStatement, ImportDeclaration } from 'estree'

const url = 'https://nextjs.org/docs/messages/no-redirect-in-try-catch'
const url =
'https://nextjs.org/docs/messages/no-redirect-in-try-catch-without-rethrow'

export = defineRule({
meta: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import rule from '@next/eslint-plugin-next/dist/rules/no-redirect-in-try-catch'
import rule from '@next/eslint-plugin-next/dist/rules/no-redirect-in-try-catch-without-rethrow'
import { RuleTester } from 'eslint'
;(RuleTester as any).setDefaultConfig({
parserOptions: {
Expand All @@ -12,7 +12,7 @@ import { RuleTester } from 'eslint'
})
const ruleTester = new RuleTester()

ruleTester.run('no-redirect-in-try-catch', rule, {
ruleTester.run('no-redirect-in-try-catch-without-rethrow', rule, {
valid: [
`'use server'
Expand Down Expand Up @@ -73,7 +73,7 @@ ruleTester.run('no-redirect-in-try-catch', rule, {
errors: [
{
message:
'When using `redirect` in a try-catch block, ensure you include `unstable_rethrow` at the start of the catch block to properly handle Next.js errors. See: https://nextjs.org/docs/messages/no-redirect-in-try-catch',
'When using `redirect` in a try-catch block, ensure you include `unstable_rethrow` at the start of the catch block to properly handle Next.js errors. See: https://nextjs.org/docs/messages/no-redirect-in-try-catch-without-rethrow',
},
],
},
Expand All @@ -96,7 +96,7 @@ ruleTester.run('no-redirect-in-try-catch', rule, {
errors: [
{
message:
'When using `redirect` in a try-catch block, ensure you include `unstable_rethrow` at the start of the catch block to properly handle Next.js errors. See: https://nextjs.org/docs/messages/no-redirect-in-try-catch',
'When using `redirect` in a try-catch block, ensure you include `unstable_rethrow` at the start of the catch block to properly handle Next.js errors. See: https://nextjs.org/docs/messages/no-redirect-in-try-catch-without-rethrow',
},
],
},
Expand All @@ -118,7 +118,7 @@ ruleTester.run('no-redirect-in-try-catch', rule, {
errors: [
{
message:
'When using `redirect` in a try-catch block, ensure you include `unstable_rethrow` at the start of the catch block to properly handle Next.js errors. See: https://nextjs.org/docs/messages/no-redirect-in-try-catch',
'When using `redirect` in a try-catch block, ensure you include `unstable_rethrow` at the start of the catch block to properly handle Next.js errors. See: https://nextjs.org/docs/messages/no-redirect-in-try-catch-without-rethrow',
},
],
},
Expand Down

0 comments on commit 6362a6f

Please sign in to comment.