diff --git a/.changeset/empty-apples-kiss.md b/.changeset/empty-apples-kiss.md new file mode 100644 index 0000000000..c05df6bffa --- /dev/null +++ b/.changeset/empty-apples-kiss.md @@ -0,0 +1,5 @@ +--- +"@clerk/remix": minor +--- + +Add support for Remix SPA Mode diff --git a/packages/remix/src/client/ClerkApp.tsx b/packages/remix/src/client/ClerkApp.tsx index a6946173dd..a0a397df8b 100644 --- a/packages/remix/src/client/ClerkApp.tsx +++ b/packages/remix/src/client/ClerkApp.tsx @@ -1,6 +1,7 @@ import { useLoaderData } from '@remix-run/react'; import React from 'react'; +import { assertPublishableKeyInSpaMode, inSpaMode } from '../utils'; import { ClerkProvider } from './RemixClerkProvider'; import type { RemixClerkProviderProps } from './types'; @@ -10,7 +11,19 @@ type ClerkAppOptions = Partial< export function ClerkApp(App: () => JSX.Element, opts: ClerkAppOptions = {}) { return () => { - const { clerkState } = useLoaderData(); + let clerkState; + const isSpaMode = inSpaMode(); + + // Don't use `useLoaderData` to fetch the clerk state if we're in SPA mode + if (!isSpaMode) { + const loaderData = useLoaderData<{ clerkState: any }>(); + clerkState = loaderData.clerkState; + } + + if (isSpaMode) { + assertPublishableKeyInSpaMode(opts.publishableKey); + } + return ( { awaitableNavigateRef.current = awaitableNavigate; @@ -45,7 +46,10 @@ export function ClerkProvider({ children, ...rest }: ClerkProviderPropsWithState const { clerkState, ...restProps } = rest; ReactClerkProvider.displayName = 'ReactClerkProvider'; - assertValidClerkState(clerkState); + if (!isSpaMode) { + assertValidClerkState(clerkState); + } + const { __clerk_ssr_state, __publishableKey, @@ -68,7 +72,9 @@ export function ClerkProvider({ children, ...rest }: ClerkProviderPropsWithState } = clerkState?.__internal_clerk_state || {}; React.useEffect(() => { - warnForSsr(clerkState); + if (!isSpaMode) { + warnForSsr(clerkState); + } }, []); React.useEffect(() => { diff --git a/packages/remix/src/client/types.ts b/packages/remix/src/client/types.ts index ef4f1ed177..4a4eedbfb9 100644 --- a/packages/remix/src/client/types.ts +++ b/packages/remix/src/client/types.ts @@ -39,3 +39,11 @@ export type RemixClerkProviderProps = Without }; // https://remix.run/blog/remix-vite-stable#cloudflare-pages-support @@ -73,3 +79,10 @@ export const getEnvVariable = (name: string, context: AppLoadContext | undefined return ''; }; + +export const inSpaMode = (): boolean => { + if (typeof window !== 'undefined' && typeof window.__remixContext?.isSpaMode !== 'undefined') { + return window.__remixContext.isSpaMode; + } + return false; +};