-
Notifications
You must be signed in to change notification settings - Fork 396
feat(elements): Remove direct reliance on next and clerk-react #4064
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
358f30d
8df5c46
6323900
234f0f5
cc4e2d1
796465f
502bd8b
c5c5c9b
0967c8a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--- | ||
"@clerk/elements": minor | ||
"@clerk/nextjs": minor | ||
"@clerk/shared": minor | ||
--- | ||
|
||
Remove `@clerk/elements` reliance on `next` and `@clerk/clerk-react` directly. The host router is now provided by `@clerk/nextjs`. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,18 @@ | ||
import { safeAccess } from '~/utils/safe-access'; | ||
|
||
export const SSO_CALLBACK_PATH_ROUTE = '/sso-callback'; | ||
export const CHOOSE_SESSION_PATH_ROUTE = '/choose'; | ||
export const MAGIC_LINK_VERIFY_PATH_ROUTE = '/verify'; | ||
|
||
export const SIGN_IN_DEFAULT_BASE_PATH = | ||
process.env.CLERK_SIGN_IN_URL ?? process.env.NEXT_PUBLIC_CLERK_SIGN_IN_URL ?? '/sign-in'; | ||
export const SIGN_UP_DEFAULT_BASE_PATH = | ||
process.env.CLERK_SIGN_UP_URL ?? process.env.NEXT_PUBLIC_CLERK_SIGN_UP_URL ?? '/sign-up'; | ||
// TODO: remove reliance on next-specific variables here | ||
export const SIGN_IN_DEFAULT_BASE_PATH = safeAccess( | ||
() => process.env.CLERK_SIGN_IN_URL ?? process.env.NEXT_PUBLIC_CLERK_SIGN_IN_URL, | ||
'/sign-in', | ||
); | ||
export const SIGN_UP_DEFAULT_BASE_PATH = safeAccess( | ||
() => process.env.CLERK_SIGN_UP_URL ?? process.env.NEXT_PUBLIC_CLERK_SIGN_UP_URL, | ||
'/sign-up', | ||
); | ||
Comment on lines
+7
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This realistically should be coming from the clerk provider / core clerk object instead of deriving it from environment variables. To maintain compat, I've just made this pull the env vars in a non-erroring way. |
||
|
||
// The version that Next added support for the window.history.pushState and replaceState APIs. | ||
// ref: https://nextjs.org/blog/next-14-1#windowhistorypushstate-and-windowhistoryreplacestate | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,2 @@ | ||
export { useNextRouter } from './next'; | ||
export { Route, Router, useClerkRouter } from '@clerk/shared/router'; | ||
export { useVirtualRouter } from './virtual'; |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export function safeAccess(fn: any, fallback: any) { | ||
try { | ||
return fn(); | ||
} catch (e) { | ||
return fallback; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
'use client'; | ||
import { ClerkProvider as ReactClerkProvider } from '@clerk/clerk-react'; | ||
import { useRouter } from 'next/navigation'; | ||
import type { ClerkHostRouter } from '@clerk/shared/router'; | ||
import { ClerkHostRouterContext } from '@clerk/shared/router'; | ||
import { usePathname, useRouter, useSearchParams } from 'next/navigation'; | ||
import React, { useEffect, useTransition } from 'react'; | ||
|
||
import { useSafeLayoutEffect } from '../../client-boundary/hooks/useSafeLayoutEffect'; | ||
|
@@ -17,12 +19,48 @@ declare global { | |
__clerk_nav_await: Array<(value: void) => void>; | ||
__clerk_nav: (to: string) => Promise<void>; | ||
__clerk_internal_invalidateCachePromise: () => void | undefined; | ||
next?: { | ||
version: string; | ||
}; | ||
} | ||
} | ||
|
||
// The version that Next added support for the window.history.pushState and replaceState APIs. | ||
// ref: https://nextjs.org/blog/next-14-1#windowhistorypushstate-and-windowhistoryreplacestate | ||
export const NEXT_WINDOW_HISTORY_SUPPORT_VERSION = '14.1.0'; | ||
|
||
/** | ||
* Clerk router integration with Next.js's router. | ||
*/ | ||
export const useNextRouter = (): ClerkHostRouter => { | ||
const router = useRouter(); | ||
const pathname = usePathname(); | ||
// eslint-disable-next-line react-hooks/rules-of-hooks -- The order doesn't differ between renders as we're checking the execution environment. | ||
const searchParams = typeof window === 'undefined' ? new URLSearchParams() : useSearchParams(); | ||
|
||
// The window.history APIs seem to prevent Next.js from triggering a full page re-render, allowing us to | ||
// preserve internal state between steps. | ||
const canUseWindowHistoryAPIs = | ||
typeof window !== 'undefined' && window.next && window.next.version >= NEXT_WINDOW_HISTORY_SUPPORT_VERSION; | ||
|
||
return { | ||
mode: 'path', | ||
name: 'NextRouter', | ||
push: (path: string) => router.push(path), | ||
replace: (path: string) => | ||
canUseWindowHistoryAPIs ? window.history.replaceState(null, '', path) : router.replace(path), | ||
shallowPush(path: string) { | ||
canUseWindowHistoryAPIs ? window.history.pushState(null, '', path) : router.push(path, {}); | ||
}, | ||
pathname: () => pathname, | ||
searchParams: () => searchParams, | ||
}; | ||
}; | ||
Comment on lines
+28
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've shifted the |
||
|
||
export const ClientClerkProvider = (props: NextClerkProviderProps) => { | ||
const { __unstable_invokeMiddlewareOnAuthStateChange = true, children } = props; | ||
const router = useRouter(); | ||
const clerkRouter = useNextRouter(); | ||
const push = useAwaitablePush(); | ||
const replace = useAwaitableReplace(); | ||
const [isPending, startTransition] = useTransition(); | ||
|
@@ -57,7 +95,6 @@ export const ClientClerkProvider = (props: NextClerkProviderProps) => { | |
return new Promise(res => { | ||
window.__clerk_internal_invalidateCachePromise = res; | ||
startTransition(() => { | ||
//@ts-expect-error next exists on window | ||
if (window.next?.version && typeof window.next.version === 'string' && window.next.version.startsWith('13')) { | ||
router.refresh(); | ||
} else { | ||
|
@@ -84,7 +121,7 @@ export const ClientClerkProvider = (props: NextClerkProviderProps) => { | |
<ClerkNextOptionsProvider options={mergedProps}> | ||
<ReactClerkProvider {...mergedProps}> | ||
<ClerkJSScript router='app' /> | ||
{children} | ||
<ClerkHostRouterContext.Provider value={clerkRouter}>{children}</ClerkHostRouterContext.Provider> | ||
</ReactClerkProvider> | ||
</ClerkNextOptionsProvider> | ||
); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔪