Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .changeset/tame-carpets-sink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
'@clerk/expo': major
---

Remove deprecated `Clerk` export in favor of `getClerkInstance()`.

```diff
- import { Clerk } from '@clerk/clerk-expo';
+ import { getClerkInstance } from '@clerk/expo';

- const token = await Clerk.session?.getToken();
+ const token = await getClerkInstance().session?.getToken();
```

If you need to create the instance before `ClerkProvider` renders, pass the `publishableKey`:

```tsx
import { ClerkProvider, getClerkInstance } from '@clerk/expo';

const clerkInstance = getClerkInstance({ publishableKey: 'pk_xxx' });

// Use the instance outside of React
const token = await clerkInstance.session?.getToken();
Comment on lines +20 to +23
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Handle potential undefined from getClerkInstance().

On web, getClerkInstance() ignores the publishableKey parameter and returns window.Clerk, which may be undefined. Add optional chaining:

 const clerkInstance = getClerkInstance({ publishableKey: 'pk_xxx' });
 
 // Use the instance outside of React
-const token = await clerkInstance.session?.getToken();
+const token = await clerkInstance?.session?.getToken();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const clerkInstance = getClerkInstance({ publishableKey: 'pk_xxx' });
// Use the instance outside of React
const token = await clerkInstance.session?.getToken();
const clerkInstance = getClerkInstance({ publishableKey: 'pk_xxx' });
// Use the instance outside of React
const token = await clerkInstance?.session?.getToken();
🤖 Prompt for AI Agents
.changeset/tame-carpets-sink.md around lines 30 to 33: getClerkInstance may
return undefined in web builds (window.Clerk), so calling .session or .getToken
on the result can throw; update the usage to guard against undefined by using
optional chaining when accessing the instance and its session (e.g., await
clerkInstance?.session?.getToken()) so the code safely returns undefined if the
Clerk instance or session is missing.

fetch('https://example.com/api', { headers: { Authorization: `Bearer ${token}` } });
```

> [!NOTE]
> - Calling `getClerkInstance()` with different publishable keys will create a new Clerk instance.
> - If `getClerkInstance` is called without a publishable key, and `ClerkProvider` has not rendered yet, an error will be thrown.
4 changes: 0 additions & 4 deletions packages/expo/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ export {
isClerkRuntimeError,
} from '@clerk/react/errors';

/**
* @deprecated Use `getClerkInstance()` instead.
*/
export { clerk as Clerk } from './provider/singleton';
export { getClerkInstance } from './provider/singleton';

export * from './provider/ClerkProvider';
Expand Down
6 changes: 1 addition & 5 deletions packages/expo/src/provider/singleton/createClerkInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ import type { BuildClerkOptions } from './types';

const KEY = '__clerk_client_jwt';

/**
* @deprecated Use `getClerkInstance()` instead. `Clerk` will be removed in the next major version.
*/
export let clerk: HeadlessBrowserClerk | BrowserClerk;
let __internal_clerk: HeadlessBrowserClerk | BrowserClerk | undefined;

export function createClerkInstance(ClerkClass: typeof Clerk) {
Expand All @@ -53,7 +49,7 @@ export function createClerkInstance(ClerkClass: typeof Clerk) {

const getToken = tokenCache.getToken;
const saveToken = tokenCache.saveToken;
__internal_clerk = clerk = new ClerkClass(publishableKey);
__internal_clerk = new ClerkClass(publishableKey);

if (Platform.OS === 'ios' || Platform.OS === 'android') {
// @ts-expect-error - This is an internal API
Expand Down
5 changes: 0 additions & 5 deletions packages/expo/src/provider/singleton/singleton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@ import { Clerk } from '@clerk/clerk-js/headless';

import { createClerkInstance } from './createClerkInstance';

/**
* @deprecated Use `getClerkInstance()` instead. `Clerk` will be removed in the next major version.
*/
export { clerk } from './createClerkInstance';

/**
* Access or create a Clerk instance outside of React. If you are using it in Expo Web then it will only access the existing instance from `window.Clerk`
* @example
Expand Down
8 changes: 2 additions & 6 deletions packages/expo/src/provider/singleton/singleton.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,8 @@ import type { BrowserClerk, HeadlessBrowserClerk } from '@clerk/react';
import type { BuildClerkOptions } from './types';

/**
* @deprecated Use `getClerkInstance()` instead. `Clerk` will be removed in the next major version.
*/
export const clerk = globalThis?.window?.Clerk;

/**
* No need to use options here as we are not creating a new instance of Clerk, we are just getting the existing instance from the window
* Access the existing Clerk instance from `window.Clerk` on the web.
* Unlike the native implementation, this does not create a new instance—it only returns the existing one set by ClerkProvider.
*/
export const getClerkInstance = (_options?: BuildClerkOptions): HeadlessBrowserClerk | BrowserClerk | undefined =>
globalThis?.window?.Clerk;
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: '`Clerk` export removed from `@clerk/expo`'
matcher: "import\\s+\\{[^}]*\\bClerk\\b[^}]*\\}\\s+from\\s+['\"]@clerk/(clerk-)?expo['\"]"
matcherFlags: 'm'
category: 'deprecation-removal'
---

The deprecated `Clerk` export has been removed from `@clerk/expo`. Use `getClerkInstance()` instead.

```diff
- import { Clerk } from '@clerk/clerk-expo';
+ import { getClerkInstance } from '@clerk/expo';

- const token = await Clerk.session?.getToken();
+ const token = await getClerkInstance().session?.getToken();
```

If you need to create the instance before `ClerkProvider` renders, pass the `publishableKey`:

```tsx
import { ClerkProvider, getClerkInstance } from '@clerk/expo';

const clerkInstance = getClerkInstance({ publishableKey: 'pk_xxx' });

// Use the instance outside of React
const token = await clerkInstance.session?.getToken();
```

> [!NOTE]
>
> - Calling `getClerkInstance()` with different publishable keys will create a new Clerk instance.
> - If `getClerkInstance` is called without a publishable key, and `ClerkProvider` has not rendered yet, an error will be thrown.
Loading