diff --git a/.eslintrc b/.eslintrc
index 859a94089..9b7e2be19 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -31,12 +31,20 @@
"node": true,
"jest": true
},
+ "overrides": [
+ {
+ "files": ["e2e/**/*.ts"],
+ "rules": {
+ "testing-library/prefer-screen-queries": "off"
+ }
+ }
+ ],
"rules": {
"func-names": [2, "as-needed"],
"no-shadow": 0,
"@typescript-eslint/no-shadow": 2,
"@typescript-eslint/explicit-function-return-type": 0,
- "@typescript-eslint/no-unused-vars": [0, {"argsIgnorePattern": "^_"}],
+ "@typescript-eslint/no-unused-vars": [0, { "argsIgnorePattern": "^_" }],
"@typescript-eslint/no-use-before-define": 0,
"@typescript-eslint/ban-ts-ignore": 0,
"@typescript-eslint/no-empty-function": 0,
@@ -44,7 +52,10 @@
"@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/explicit-module-boundary-types": 0,
- "@typescript-eslint/consistent-type-imports": [2, {"prefer": "type-imports"}],
+ "@typescript-eslint/consistent-type-imports": [
+ 2,
+ { "prefer": "type-imports" }
+ ],
"@typescript-eslint/ban-types": 0,
"react-hooks/rules-of-hooks": 2,
"react-hooks/exhaustive-deps": 1,
diff --git a/e2e/site/app/issue-2702/page.tsx b/e2e/site/app/issue-2702/page.tsx
new file mode 100644
index 000000000..3518c8721
--- /dev/null
+++ b/e2e/site/app/issue-2702/page.tsx
@@ -0,0 +1,9 @@
+import Comp from './reproduction'
+
+export default function Page() {
+ return (
+
+
+
+ )
+}
diff --git a/e2e/site/app/issue-2702/reproduction.tsx b/e2e/site/app/issue-2702/reproduction.tsx
new file mode 100644
index 000000000..0544f3334
--- /dev/null
+++ b/e2e/site/app/issue-2702/reproduction.tsx
@@ -0,0 +1,41 @@
+'use client'
+import useSWR, { preload } from 'swr'
+import { Suspense, use, useEffect, useState } from 'react'
+
+const sleep = (time: number, data: string) =>
+ new Promise(resolve => {
+ setTimeout(() => resolve(data), time)
+ })
+
+const Bug = () => {
+ const a = use(preload('a', () => sleep(1000, 'a')))
+ const { data: b } = useSWR('b', () => sleep(2000, 'b'), {
+ suspense: true
+ })
+ useState(b)
+ return (
+
+ {a},{b}
+
+ )
+}
+
+const Comp = () => {
+ const [loading, setLoading] = useState(true)
+
+ // To prevent SSR
+ useEffect(() => {
+ setLoading(false)
+ }, [])
+
+ if (loading) {
+ return Loading...
+ }
+ return (
+ fetching}>
+
+
+ )
+}
+
+export default Comp
diff --git a/e2e/test/issue-2702-too-many-hooks.ts b/e2e/test/issue-2702-too-many-hooks.ts
new file mode 100644
index 000000000..d4efeffe2
--- /dev/null
+++ b/e2e/test/issue-2702-too-many-hooks.ts
@@ -0,0 +1,14 @@
+import { test, expect } from '@playwright/test'
+
+test.describe('issue 2702', () => {
+ test('should not crash with too many hooks', async ({ page }) => {
+ // Navigate to the test page
+ await page.goto('./issue-2702', { waitUntil: 'networkidle' })
+
+ // Wait for the page to be fully loaded and interactive
+ await expect(page.getByText('fetching')).toBeVisible()
+
+ // Verify that the component renders correctly
+ await expect(page.getByText('a,b')).toBeVisible()
+ })
+})