feat: add check-parent-suspense ESLint rule
This PR implements a new ESLint rule @suspensive/check-parent-suspense that ensures components using Suspense-related APIs are properly wrapped in a Suspense boundary.
What it does
The rule detects usage of Suspense-related APIs and validates they are wrapped in a <Suspense> component:
Detected APIs:
-
Hooks:
useSuspenseQuery,useSuspenseInfiniteQuery,useSuspenseQueries -
Components:
SuspenseQuery,SuspenseInfiniteQuery,SuspenseQueries -
Lazy Components: Components created with
lazy()function
Configuration
The rule is enabled by default in React TypeScript configurations but disabled for all files in packages/** to exempt library code from the check while still enforcing it in application code and examples.
Examples
❌ Before (produces errors):
function MyComponent() {
const data = useSuspenseQuery(queryOptions) // Error: missing Suspense wrapper
return <div>{data}</div>
}
function App() {
return <SuspenseQuery>{data => <div>{data}</div>}</SuspenseQuery> // Error: missing Suspense wrapper
}
✅ After (correct usage):
function MyComponent() {
return (
<Suspense fallback={<div>Loading...</div>}>
<div>
{(() => {
const data = useSuspenseQuery(queryOptions)
return <div>{data}</div>
})()}
</div>
</Suspense>
)
}
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<SuspenseQuery>{data => <div>{data}</div>}</SuspenseQuery>
</Suspense>
)
}
Implementation details
-
Location:
configs/eslint-config/rules/check-parent-suspense.js -
Integration: Added to
@suspensive/eslint-configand enabled by default in React TypeScript configurations -
Package Exemption: Disabled for
packages/**/*.{ts,tsx}files to allow library components that are designed to be used within Suspense boundaries - Configurable: Supports custom hook names, component names, and Suspense wrapper names
- Comprehensive testing: Full test suite with valid/invalid cases
- Documentation: Complete rule documentation with examples and configuration options
Recent Updates
- ✅ Successfully rebased onto latest main (includes commits through e34d368)
- ✅ Resolved merge conflicts in
configs/eslint-config/package.jsonandpnpm-lock.yaml - ✅ All ESLint rule tests passing after rebase
- ✅ Package exemptions preserved - rule disabled for
packages/**/*.{ts,tsx}files
Real-world impact
The rule successfully identified several legitimate issues in the existing codebase where Suspense-related APIs were used without proper Suspense boundaries, demonstrating its practical value for preventing runtime errors.
For cases where the rule is too strict, developers can use // eslint-disable-next-line @suspensive/check-parent-suspense to disable the rule locally, though this is typically not needed since library code in packages is automatically exempted.
Fixes #1654.
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.
The latest updates on your projects. Learn more about Vercel for GitHub.
| Project | Deployment | Preview | Comments | Updated (UTC) |
|---|---|---|---|---|
| v2.suspensive.org | Preview | Comment | Sep 25, 2025 5:16pm | |
| v3.suspensive.org | Preview | Comment | Sep 25, 2025 5:16pm | |
| visualization.suspensive.org | Sep 25, 2025 5:16pm |
⚠️ No Changeset found
Latest commit: 214626958741210f1498eec406ee8b7d6e2a900d
Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.
This PR includes no changesets
When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types
Click here to learn what changesets are, and how to add one.
Click here if you're a maintainer who wants to add a changeset to this PR
@copilot rebase please
People can be co-author:
| Candidate | Reasons | Count | Add this as commit message |
|---|---|---|---|
| @manudeli | https://github.com/toss/suspensive/pull/1738#discussion_r2379747051 https://github.com/toss/suspensive/pull/1738#pullrequestreview-3268649883 https://github.com/toss/suspensive/pull/1738#issuecomment-3329384242 https://github.com/toss/suspensive/pull/1738#issuecomment-3334963697 https://github.com/toss/suspensive/pull/1738#issuecomment-3334982457 https://github.com/toss/suspensive/pull/1738#issuecomment-3336768337 | 6 | Co-authored-by: manudeli <[email protected]> |
| @Copilot | https://github.com/toss/suspensive/pull/1738#discussion_r2379716385 https://github.com/toss/suspensive/pull/1738#discussion_r2379763982 https://github.com/toss/suspensive/pull/1738#issuecomment-3335011677 https://github.com/toss/suspensive/pull/1738#issuecomment-3336776171 https://github.com/toss/suspensive/pull/1738 | 5 | Co-authored-by: Copilot <[email protected]> |
| @2-NOW | https://github.com/toss/suspensive/pull/1738#issuecomment-3336691174 | 1 | Co-authored-by: 2-NOW <[email protected]> |
| @gwansikk | https://github.com/toss/suspensive/pull/1738#issuecomment-3343707900 | 1 | Co-authored-by: gwansikk <[email protected]> |
@copilot resolve confilct
@2-NOW Could you review this with me? because this is your idea initially
@copilot resolve confilct
I've resolved the merge conflicts and successfully rebased the branch onto main. The conflicts were in:
-
configs/eslint-config/package.json: Updated typescript-eslint version to ^8.43.0 -
pnpm-lock.yaml: Regenerated after resolving dependency conflicts
The rebase is complete and all ESLint rule tests are still passing. The branch is now ready for review with the latest main branch changes integrated.
Commit: 2affdbc
@2-NOW Could you review this with me? because this is your idea initially
Sure! Thank you for giving me the opportunity.
@copilot resolve conflict
@copilot resolve conflict
I've successfully resolved the merge conflicts and rebased the branch onto the latest main. The conflicts were in:
-
configs/eslint-config/package.json: Updated typescript-eslint version to ^8.43.0 -
pnpm-lock.yaml: Regenerated after resolving dependency conflicts
The rebase is complete and all ESLint rule tests are still passing. The branch is now up to date with the latest main branch changes.
Commit: 0ded5c5
I love it! I really hope this works. I'll review it as well!