Skip to content

Conversation

@jacekradko
Copy link
Member

@jacekradko jacekradko commented Nov 5, 2025

Description

When isomorphicClerk is loaded, we should return isLoaded: false from useAuth() when transitive state is set.

The check ensures we only override auth state with initial values when Clerk SDK hasn't loaded yet. Once loaded, we respect the actual auth state, even if it's transitioning, so components know to wait until session data is fully resolved.

Screenshot 2025-11-05 at 3 09 16 PM

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

  • Bug Fixes

    • Authentication hook now reports isLoaded = false when the auth system is in a transitive/loading state to avoid showing stale auth status.
  • Tests

    • Added a test verifying the hook returns isLoaded = false and no session/user IDs while auth is transitive.
  • Chores

    • Added release metadata for a patch version bump.

@changeset-bot
Copy link

changeset-bot bot commented Nov 5, 2025

🦋 Changeset detected

Latest commit: 0f3f02f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 8 packages
Name Type
@clerk/clerk-react Patch
@clerk/chrome-extension Patch
@clerk/elements Patch
@clerk/clerk-expo Patch
@clerk/nextjs Patch
@clerk/react-router Patch
@clerk/remix Patch
@clerk/tanstack-react-start Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Nov 5, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
clerk-js-sandbox Ready Ready Preview Comment Nov 7, 2025 4:00pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 5, 2025

Walkthrough

Modify useAuth to select auth context based on isomorphicClerk.isLoaded; add a test that asserts useAuth returns isLoaded = false when isomorphicClerk is loaded but in a transitive state; add a patch changeset for @clerk/clerk-react documenting this behavior.

Changes

Cohort / File(s) Summary
Test: transitive auth state
packages/react/src/hooks/__tests__/useAuth.test.tsx
Adds a test that stubs an isomorphicClerk with loaded: true but transitive state and asserts useAuth returns isLoaded = false, and that isSignedIn, sessionId, and userId are undefined.
Hook initialization & helpers
packages/react/src/hooks/useAuth.ts
Consolidates authContext selection to prefer initialAuthState only when isomorphicClerk.isLoaded is false; removes later redeclaration and uses the unified authContext for getToken and signOut helpers.
Changeset / Release note
.changeset/full-showers-serve.md
Adds a patch changeset for @clerk/clerk-react documenting that useAuth() reports isLoaded=false when isomorphicClerk is loaded but the app is in a transitive state.

Sequence Diagram(s)

sequenceDiagram
    participant Component
    participant useAuth
    participant ISC as IsomorphicClerk
    participant AuthCtx as AuthContext
    participant Helpers as getToken/signOut

    Component->>useAuth: invoke hook
    useAuth->>ISC: read isLoaded
    ISC-->>useAuth: isLoaded flag

    alt ISC not loaded OR transitive
        useAuth->>AuthCtx: use initialAuthState (report isLoaded=false)
        note right of AuthCtx `#f0f0f0`: no session/user IDs
        useAuth-->>Component: return derived auth (isLoaded=false, undefined ids)
    else ISC ready
        useAuth->>AuthCtx: use existing authContext
        useAuth->>Helpers: create helpers with ISC
        Helpers-->>useAuth: helper functions
        useAuth-->>Component: return derived auth (isLoaded=true, populated ids)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • Review focus:
    • packages/react/src/hooks/useAuth.ts: verify unified authContext logic, no shadowing, correct isLoaded guard.
    • packages/react/src/hooks/__tests__/useAuth.test.tsx: ensure the mocked transitive state accurately simulates behavior and assertions match public API.
    • .changeset/full-showers-serve.md: verify package target and wording.

Poem

🐇 I sniffed a loaded, foggy day,
A middling state where bits delay,
I sit and wait, report "not done",
Till clearer light reveals the sun,
A tiny test hops — now we're on our way.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main fix: correcting useAuth().isLoaded behavior in transitive state, which directly reflects the core change across the modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/useAuth-isLoaded-transitive-state

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b358394 and 0f3f02f.

📒 Files selected for processing (1)
  • packages/react/src/hooks/useAuth.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/react/src/hooks/useAuth.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Build Packages
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: Analyze (javascript-typescript)

Comment @coderabbitai help to get the list of available commands and usage tips.

@jacekradko
Copy link
Member Author

!snapshot

@clerk-cookie
Copy link
Collaborator

Hey @jacekradko - the snapshot version command generated the following package versions:

Package Version
@clerk/agent-toolkit 0.1.47-snapshot.v20251105162613
@clerk/astro 2.14.5-snapshot.v20251105162613
@clerk/backend 2.19.4-snapshot.v20251105162613
@clerk/chrome-extension 2.7.13-snapshot.v20251105162613
@clerk/clerk-js 5.104.1-snapshot.v20251105162613
@clerk/elements 0.23.78-snapshot.v20251105162613
@clerk/clerk-expo 2.18.2-snapshot.v20251105162613
@clerk/expo-passkeys 0.4.15-snapshot.v20251105162613
@clerk/express 1.7.46-snapshot.v20251105162613
@clerk/fastify 2.5.3-snapshot.v20251105162613
@clerk/localizations 3.26.7-snapshot.v20251105162613
@clerk/nextjs 6.34.4-snapshot.v20251105162613
@clerk/nuxt 1.11.5-snapshot.v20251105162613
@clerk/clerk-react 5.53.7-snapshot.v20251105162613
@clerk/react-router 2.1.9-snapshot.v20251105162613
@clerk/remix 4.13.12-snapshot.v20251105162613
@clerk/shared 3.31.1-snapshot.v20251105162613
@clerk/tanstack-react-start 0.26.8-snapshot.v20251105162613
@clerk/testing 1.13.12-snapshot.v20251105162613
@clerk/themes 2.4.33-snapshot.v20251105162613
@clerk/types 4.97.2-snapshot.v20251105162613
@clerk/vue 1.14.12-snapshot.v20251105162613

Tip: Use the snippet copy button below to quickly install the required packages.
@clerk/agent-toolkit

npm i @clerk/agent-toolkit@0.1.47-snapshot.v20251105162613 --save-exact

@clerk/astro

npm i @clerk/astro@2.14.5-snapshot.v20251105162613 --save-exact

@clerk/backend

npm i @clerk/backend@2.19.4-snapshot.v20251105162613 --save-exact

@clerk/chrome-extension

npm i @clerk/chrome-extension@2.7.13-snapshot.v20251105162613 --save-exact

@clerk/clerk-js

npm i @clerk/clerk-js@5.104.1-snapshot.v20251105162613 --save-exact

@clerk/elements

npm i @clerk/elements@0.23.78-snapshot.v20251105162613 --save-exact

@clerk/clerk-expo

npm i @clerk/clerk-expo@2.18.2-snapshot.v20251105162613 --save-exact

@clerk/expo-passkeys

npm i @clerk/expo-passkeys@0.4.15-snapshot.v20251105162613 --save-exact

@clerk/express

npm i @clerk/express@1.7.46-snapshot.v20251105162613 --save-exact

@clerk/fastify

npm i @clerk/fastify@2.5.3-snapshot.v20251105162613 --save-exact

@clerk/localizations

npm i @clerk/localizations@3.26.7-snapshot.v20251105162613 --save-exact

@clerk/nextjs

npm i @clerk/nextjs@6.34.4-snapshot.v20251105162613 --save-exact

@clerk/nuxt

npm i @clerk/nuxt@1.11.5-snapshot.v20251105162613 --save-exact

@clerk/clerk-react

npm i @clerk/clerk-react@5.53.7-snapshot.v20251105162613 --save-exact

@clerk/react-router

npm i @clerk/react-router@2.1.9-snapshot.v20251105162613 --save-exact

@clerk/remix

npm i @clerk/remix@4.13.12-snapshot.v20251105162613 --save-exact

@clerk/shared

npm i @clerk/shared@3.31.1-snapshot.v20251105162613 --save-exact

@clerk/tanstack-react-start

npm i @clerk/tanstack-react-start@0.26.8-snapshot.v20251105162613 --save-exact

@clerk/testing

npm i @clerk/testing@1.13.12-snapshot.v20251105162613 --save-exact

@clerk/themes

npm i @clerk/themes@2.4.33-snapshot.v20251105162613 --save-exact

@clerk/types

npm i @clerk/types@4.97.2-snapshot.v20251105162613 --save-exact

@clerk/vue

npm i @clerk/vue@1.14.12-snapshot.v20251105162613 --save-exact

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 5, 2025

Open in StackBlitz

@clerk/agent-toolkit

npm i https://pkg.pr.new/@clerk/agent-toolkit@7157

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@7157

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@7157

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@7157

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@7157

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@7157

@clerk/elements

npm i https://pkg.pr.new/@clerk/elements@7157

@clerk/clerk-expo

npm i https://pkg.pr.new/@clerk/clerk-expo@7157

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@7157

@clerk/express

npm i https://pkg.pr.new/@clerk/express@7157

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@7157

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@7157

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@7157

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@7157

@clerk/clerk-react

npm i https://pkg.pr.new/@clerk/clerk-react@7157

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@7157

@clerk/remix

npm i https://pkg.pr.new/@clerk/remix@7157

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@7157

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@7157

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@7157

@clerk/themes

npm i https://pkg.pr.new/@clerk/themes@7157

@clerk/types

npm i https://pkg.pr.new/@clerk/types@7157

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@7157

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@7157

commit: 0f3f02f

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
packages/react/src/hooks/useAuth.ts (2)

105-107: Verify the guard logic with integration tests.

The updated condition correctly handles the transitive state by resetting authContext only when Clerk is not loaded AND both sessionId and userId are undefined. This ensures isLoaded returns false during the loading phase.

However, the actual logic change in useAuth is not directly covered by integration tests. Consider adding test cases that specifically verify useAuth behavior with different isomorphicClerk.loaded values:

  1. When isomorphicClerk.loaded = false with no auth data → should return not loaded
  2. When isomorphicClerk.loaded = true with no auth data → should return loaded but not signed in
  3. When isomorphicClerk.loaded = false but auth data exists (SSR scenario) → should use the auth data

Would you like me to generate test cases that cover these scenarios?


98-99: Consider replacing as any with proper typing.

The as any type assertion bypasses TypeScript's type safety. Consider using unknown with type guards or defining an explicit type for initialAuthState.

  const { treatPendingAsSignedOut, ...rest } = initialAuthStateOrOptions ?? {};
- const initialAuthState = rest as any;
+ const initialAuthState = rest as unknown;

Alternatively, define a proper interface for the expected shape of initialAuthState.

As per coding guidelines.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5536429 and 35b2865.

📒 Files selected for processing (2)
  • packages/react/src/hooks/__tests__/useAuth.test.tsx (1 hunks)
  • packages/react/src/hooks/useAuth.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
  • packages/react/src/hooks/useAuth.ts
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
  • packages/react/src/hooks/useAuth.ts
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

TypeScript is required for all packages

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
  • packages/react/src/hooks/useAuth.ts
packages/**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Packages should export TypeScript types alongside runtime code

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
  • packages/react/src/hooks/useAuth.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
  • packages/react/src/hooks/useAuth.ts
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components

**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components: UserProfile, NavigationMenu
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
packages/**/*.{test,spec}.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Unit tests should use Jest or Vitest as the test runner.

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
  • packages/react/src/hooks/useAuth.ts
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

**/*.tsx: Use proper type definitions for props and state
Leverage TypeScript's type inference where possible
Use proper event types for handlers
Implement proper generic types for reusable components
Use proper type guards for conditional rendering

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/*.test.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

**/*.test.{jsx,tsx}: Use React Testing Library
Test component behavior, not implementation
Use proper test queries
Implement proper test isolation
Use proper test coverage
Test component interactions
Use proper test data
Implement proper test setup
Use proper test cleanup
Implement proper test assertions
Use proper test structure

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/__tests__/**/*.{ts,tsx}: Create type-safe test builders/factories
Use branded types for test isolation
Implement proper mock types that match interfaces

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
🧬 Code graph analysis (1)
packages/react/src/hooks/__tests__/useAuth.test.tsx (1)
packages/react/src/hooks/useAuth.ts (1)
  • useDerivedAuth (152-194)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Build Packages
  • GitHub Check: triage
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (3)
packages/react/src/hooks/useAuth.ts (2)

102-102: LGTM: Early initialization improves clarity.

Initializing isomorphicClerk early makes the dependency explicit and enables its use in the guard condition below.


109-110: LGTM: Correct usage of early-initialized variable.

Using the early-initialized isomorphicClerk eliminates the need for redeclaration and improves code organization.

packages/react/src/hooks/__tests__/useAuth.test.tsx (1)

321-345: Valid test for transitive state with partial initialization.

This test extends coverage by validating that when an auth object has methods (signOut, getToken) but incomplete data fields (undefined sessionId, userId), isLoaded correctly returns false. This represents a realistic transitive state where the Clerk instance exists but authentication data is still loading.

The test differs meaningfully from the existing test at lines 87-102 by explicitly setting multiple fields and including methods, rather than using an empty object.

Note: This test validates useDerivedAuth behavior. The actual fix in useAuth.ts (line 105 checking isomorphicClerk.loaded) would benefit from additional integration tests as mentioned in the previous review comment.

@jacekradko jacekradko changed the title fix(react): Set isLoaded to false during transitive state fix(clerk-react): Set isLoaded to false during transitive state Nov 5, 2025
@blacksmith-sh

This comment has been minimized.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/react/src/hooks/__tests__/useAuth.test.tsx (1)

82-85: Consider improving mock type safety.

The mock uses as any type assertion which bypasses TypeScript's type checking. For better type safety, consider using a more specific type:

-    const mockIsomorphicClerk = {
+    const mockIsomorphicClerk: Partial<LoadedClerk> = {
       loaded: true,
       telemetry: { record: vi.fn() },
     };

And update the provider:

-        <ClerkInstanceContext.Provider value={{ value: mockIsomorphicClerk as any }}>
+        <ClerkInstanceContext.Provider value={{ value: mockIsomorphicClerk as LoadedClerk }}>

Also applies to: 102-102

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between eb81b28 and 77d7628.

📒 Files selected for processing (1)
  • packages/react/src/hooks/__tests__/useAuth.test.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

TypeScript is required for all packages

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
packages/**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Packages should export TypeScript types alongside runtime code

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components

**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components: UserProfile, NavigationMenu
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
packages/**/*.{test,spec}.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Unit tests should use Jest or Vitest as the test runner.

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

**/*.tsx: Use proper type definitions for props and state
Leverage TypeScript's type inference where possible
Use proper event types for handlers
Implement proper generic types for reusable components
Use proper type guards for conditional rendering

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/*.test.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

**/*.test.{jsx,tsx}: Use React Testing Library
Test component behavior, not implementation
Use proper test queries
Implement proper test isolation
Use proper test coverage
Test component interactions
Use proper test data
Implement proper test setup
Use proper test cleanup
Implement proper test assertions
Use proper test structure

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/__tests__/**/*.{ts,tsx}: Create type-safe test builders/factories
Use branded types for test isolation
Implement proper mock types that match interfaces

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
🧬 Code graph analysis (1)
packages/react/src/hooks/__tests__/useAuth.test.tsx (2)
packages/react/src/hooks/useAuth.ts (1)
  • useAuth (95-124)
packages/react/src/contexts/AuthContext.ts (1)
  • AuthContext (23-23)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build Packages
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan
🔇 Additional comments (1)
packages/react/src/hooks/__tests__/useAuth.test.tsx (1)

81-112: Test correctly validates transitive state behavior.

The test properly verifies that useAuth() returns isLoaded: false when the Clerk SDK is loaded but the auth state is in a transitive (undetermined) state with undefined sessionId and userId. The test structure follows established patterns and React Testing Library best practices.

@jacekradko jacekradko changed the title fix(clerk-react): Set isLoaded to false during transitive state fix(clerk-react): Correct useAuth().isLoaded in transitive state Nov 5, 2025
@jacekradko jacekradko requested review from Ephem and brkalow November 5, 2025 21:26
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/react/src/hooks/__tests__/useAuth.test.tsx (1)

81-112: Test correctly verifies the transitive state fix.

The test logic is sound and properly validates the PR's objective: when isomorphicClerk is loaded but the auth context contains undefined values (transitive state), useAuth() should return isLoaded: false. The mock setup and assertions accurately reflect this scenario.

Consider extracting mock creation to typed factory functions to improve type safety and reusability:

const createMockIsomorphicClerk = (overrides?: Partial<LoadedClerk>): LoadedClerk => ({
  loaded: true,
  telemetry: { record: vi.fn() },
  // ... other required LoadedClerk properties with sensible defaults
  ...overrides,
} as LoadedClerk);

const createMockAuthContext = (overrides?: Partial<AuthContextValue>): AuthContextValue => ({
  actor: undefined,
  factorVerificationAge: null,
  orgId: undefined,
  orgPermissions: undefined,
  orgRole: undefined,
  orgSlug: undefined,
  sessionClaims: null,
  sessionId: undefined,
  sessionStatus: undefined,
  userId: undefined,
  ...overrides,
} as AuthContextValue);

Then use them in the test:

-  const mockIsomorphicClerk = {
-    loaded: true,
-    telemetry: { record: vi.fn() },
-  };
-
-  const mockAuthContext = {
-    actor: undefined,
-    factorVerificationAge: null,
-    orgId: undefined,
-    orgPermissions: undefined,
-    orgRole: undefined,
-    orgSlug: undefined,
-    sessionClaims: null,
-    sessionId: undefined,
-    sessionStatus: undefined,
-    userId: undefined,
-  };
+  const mockIsomorphicClerk = createMockIsomorphicClerk({ loaded: true });
+  const mockAuthContext = createMockAuthContext();

This approach follows the guideline to "create type-safe test builders/factories" and reduces the use of as any casts.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 044d9ca and b358394.

📒 Files selected for processing (1)
  • packages/react/src/hooks/__tests__/useAuth.test.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.{js,jsx,ts,tsx}: All code must pass ESLint checks with the project's configuration
Follow established naming conventions (PascalCase for components, camelCase for variables)
Maintain comprehensive JSDoc comments for public APIs
Use dynamic imports for optional features
All public APIs must be documented with JSDoc
Provide meaningful error messages to developers
Include error recovery suggestions where applicable
Log errors appropriately for debugging
Lazy load components and features when possible
Implement proper caching strategies
Use efficient data structures and algorithms
Profile and optimize critical paths
Validate all inputs and sanitize outputs
Implement proper logging with different levels

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/*.{js,jsx,ts,tsx,json,css,scss,md,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use Prettier for consistent code formatting

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

TypeScript is required for all packages

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
packages/**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Packages should export TypeScript types alongside runtime code

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

Use proper TypeScript error types

**/*.{ts,tsx}: Always define explicit return types for functions, especially public APIs
Use proper type annotations for variables and parameters where inference isn't clear
Avoid any type - prefer unknown when type is uncertain, then narrow with type guards
Use interface for object shapes that might be extended
Use type for unions, primitives, and computed types
Prefer readonly properties for immutable data structures
Use private for internal implementation details
Use protected for inheritance hierarchies
Use public explicitly for clarity in public APIs
Prefer readonly for properties that shouldn't change after construction
Prefer composition and interfaces over deep inheritance chains
Use mixins for shared behavior across unrelated classes
Implement dependency injection for loose coupling
Let TypeScript infer when types are obvious
Use const assertions for literal types: as const
Use satisfies operator for type checking without widening
Use mapped types for transforming object types
Use conditional types for type-level logic
Leverage template literal types for string manipulation
Use ES6 imports/exports consistently
Use default exports sparingly, prefer named exports
Use type-only imports: import type { ... } from ...
No any types without justification
Proper error handling with typed errors
Consistent use of readonly for immutable data
Proper generic constraints
No unused type parameters
Proper use of utility types instead of manual type construction
Type-only imports where possible
Proper tree-shaking friendly exports
No circular dependencies
Efficient type computations (avoid deep recursion)

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/development.mdc)

**/*.{jsx,tsx}: Use error boundaries in React components
Minimize re-renders in React components

**/*.{jsx,tsx}: Always use functional components with hooks instead of class components
Follow PascalCase naming for components: UserProfile, NavigationMenu
Keep components focused on a single responsibility - split large components
Limit component size to 150-200 lines; extract logic into custom hooks
Use composition over inheritance - prefer smaller, composable components
Export components as named exports for better tree-shaking
One component per file with matching filename and component name
Use useState for simple state management
Use useReducer for complex state logic
Implement proper state initialization
Use proper state updates with callbacks
Implement proper state cleanup
Use Context API for theme/authentication
Implement proper state selectors
Use proper state normalization
Implement proper state persistence
Use React.memo for expensive components
Implement proper useCallback for handlers
Use proper useMemo for expensive computations
Implement proper virtualization for lists
Use proper code splitting with React.lazy
Implement proper cleanup in useEffect
Use proper refs for DOM access
Implement proper event listener cleanup
Use proper abort controllers for fetch
Implement proper subscription cleanup
Use proper HTML elements
Implement proper ARIA attributes
Use proper heading hierarchy
Implement proper form labels
Use proper button types
Implement proper focus management
Use proper keyboard shortcuts
Implement proper tab order
Use proper skip links
Implement proper focus traps
Implement proper error boundaries
Use proper error logging
Implement proper error recovery
Use proper error messages
Implement proper error fallbacks
Use proper form validation
Implement proper error states
Use proper error messages
Implement proper form submission
Use proper form reset
Use proper component naming
Implement proper file naming
Use proper prop naming
Implement proper...

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
packages/**/*.{test,spec}.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Unit tests should use Jest or Vitest as the test runner.

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/*.{js,ts,tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/monorepo.mdc)

Support multiple Clerk environment variables (CLERK_, NEXT_PUBLIC_CLERK_, etc.) for configuration.

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

**/*.tsx: Use proper type definitions for props and state
Leverage TypeScript's type inference where possible
Use proper event types for handlers
Implement proper generic types for reusable components
Use proper type guards for conditional rendering

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/*.test.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

**/*.test.{jsx,tsx}: Use React Testing Library
Test component behavior, not implementation
Use proper test queries
Implement proper test isolation
Use proper test coverage
Test component interactions
Use proper test data
Implement proper test setup
Use proper test cleanup
Implement proper test assertions
Use proper test structure

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/__tests__/**/*.{ts,tsx}: Create type-safe test builders/factories
Use branded types for test isolation
Implement proper mock types that match interfaces

Files:

  • packages/react/src/hooks/__tests__/useAuth.test.tsx
🧬 Code graph analysis (1)
packages/react/src/hooks/__tests__/useAuth.test.tsx (3)
packages/clerk-js/src/test/utils.ts (1)
  • renderHook (77-77)
packages/react/src/hooks/useAuth.ts (1)
  • useAuth (95-120)
packages/react/src/contexts/AuthContext.ts (1)
  • AuthContext (23-23)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build Packages
  • GitHub Check: Formatting | Dedupe | Changeset
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: semgrep-cloud-platform/scan

@blacksmith-sh

This comment has been minimized.

Comment on lines -104 to -106
if (authContext.sessionId === undefined && authContext.userId === undefined) {
authContext = initialAuthState != null ? initialAuthState : {};
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, so previously it was falling back to the initial auth state when sessionId and userId was undefined? This was likely fine in CSR apps as the initial state there would be isLoading: true, but not so fine in SSRd apps.

I think you might have stumbled on the root cause of the sign in bug here too! When signing in, the initial state would be sessionId: null, user is signed out. When sign in transitions to the transitive state, sessionId and userId becomes undefined, so this would fall back to the initial state, which is null.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this PR fixes the sign in bug independently of the other one:

CleanShot 2025-11-06 at 10 53 06

}

const isomorphicClerk = useIsomorphicClerkContext();
const authContext = !isomorphicClerk.loaded && initialAuthState ? initialAuthState : authContextFromHook;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a separate existing issue, but since you are touching the code I thought I might comment on it in context, not suggesting we tackle it here since it's a bigger one.

With SSR, initialAuthState is always what will have been used. With this code, if Clerk has loaded before this part of the application has hydrated (selective hydration can defer hydrating Suspense boundaries), this would use the hook state, which might differ from the initialAuthState, causing hydration mismatches. This is probably most likely with static SSR builds.

The canonical fix would be to use useSyncExternalStore and pass the initial state to the getServerSnapshot function. Since we are using context here there's nothing to subscribe to though, so not sure how that plays out.

We also can't use useSyncExternalStore in the ClerkProvider (where we do listen to the Clerk store), since that wouldn't work with selective hydration, it would only use getServerSnapshot when that part of the application was hydrating.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants