Skip to content

Step 10 sample code for Clerk auth violates React rule: never pass Hooks as values #151

@SuperJakov

Description

@SuperJakov

Summary

The code shown in Step 9 of the Clerk integration guide passes the useAuth Hook itself as a prop, which violates the React rule:

Never pass around Hooks as regular values
React docs

This can disable future React Compiler optimizations and complicates static analysis.

Problem location

File: /npm-packages/docs/docs/auth/clerk.mdx Line 334
Section: Step 9: Configure ConvexProviderWithClerk

Current snippet:

<ConvexProviderWithClerk client={convex} useAuth={useAuth}>

useAuth is a Hook, but it is being passed as a plain value (useAuth={useAuth}).

Root cause & correct pattern

useAuth must be called inside a component that is already wrapped by <ClerkProvider>.
Therefore we need two components:

  1. A leaf component that renders <ConvexProviderWithClerk> and calls useAuth() inside it.
  2. A root provider that wraps everything in <ClerkProvider>.

This satisfies both:

  • React Rules of Hooks
  • Clerk’s requirement that useAuth() be used within <ClerkProvider>

Suggested fix

React example

Replace the single provider file with:

// convex-client-provider.tsx
"use client";
import { ReactNode } from "react";
import { ConvexReactClient } from "convex/react";
import { ConvexProviderWithClerk } from "convex/react-clerk";
import { useAuth } from "@clerk/clerk-react";

const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string);

export default function ConvexClientProvider({ children }: { children: ReactNode }) {
  const auth = useAuth();               
  return (
    <ConvexProviderWithClerk
      client={convex}
      useAuth={() => auth}              
    >
      {children}
    </ConvexProviderWithClerk>
  );
}

and in your root:

// main.tsx (or App.tsx)
import { ClerkProvider } from "@clerk/clerk-react";
import ConvexClientProvider from "./convex-client-provider";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <ClerkProvider publishableKey={import.meta.env.VITE_CLERK_PUBLISHABLE_KEY}>
      <ConvexClientProvider>
        <App />
      </ConvexClientProvider>
    </ClerkProvider>
  </React.StrictMode>
);

Impact

  • Keeps the sample compliant with React rules
  • Avoids potential React Compiler warnings / optimisation failures
  • Requires no breaking changes to the <ConvexProviderWithClerk> API

Happy to open a PR if this looks good!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions