Skip to content

Commit

Permalink
fix(elements): Routing for Next 14.1 [SDK-1539] (#3018)
Browse files Browse the repository at this point in the history
* fix(elements): Routing for Next 14.1

* chore(elements): Rename check for clarity

* chore(elements): Adjust comment

* chore(elements): Add comment above constant

* chore(repo): Add changeset

* chore(elements): Bump version

---------

Co-authored-by: Bryce Kalow <bryce@clerk.dev>
  • Loading branch information
tmilewski and BRKalow authored Mar 22, 2024
1 parent 2395b6b commit 71319f1
Show file tree
Hide file tree
Showing 8 changed files with 26 additions and 14 deletions.
2 changes: 2 additions & 0 deletions .changeset/eight-mangos-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
2 changes: 1 addition & 1 deletion packages/elements/examples/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"clsx": "^2.0.0",
"framer-motion": "^11.0.2",
"geist": "^1.2.2",
"next": "~14.0.0",
"next": "~14.1.0",
"react": "^18",
"react-dom": "^18"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/elements/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@clerk/elements",
"version": "0.1.30",
"version": "0.1.31",
"description": "Clerk Elements",
"keywords": [
"clerk",
Expand Down
4 changes: 3 additions & 1 deletion packages/elements/src/internals/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ export const MAGIC_LINK_VERIFY_PATH_ROUTE = '/verify';
export const SIGN_IN_DEFAULT_BASE_PATH = '/sign-in';
export const SIGN_UP_DEFAULT_BASE_PATH = '/sign-up';

export const NEXT_ROUTING_CHANGE_VERSION = '14.1.0';
// 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';

export const SEARCH_PARAMS = {
createdSession: '__clerk_created_session',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { createActorContext } from '@xstate/react';
import type { SnapshotFrom } from 'xstate';

import { FormMachine } from '~/internals/machines/form/form.machine';
import { consoleInspector } from '~/internals/utils/inspector';

export type SnapshotState = SnapshotFrom<typeof FormMachine>;

const FormMachineContext = createActorContext(FormMachine);
const FormMachineContext = createActorContext(FormMachine, { inspect: consoleInspector });

export const FormStoreProvider = FormMachineContext.Provider;
export const useFormStore = FormMachineContext.useActorRef;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NEXT_ROUTING_CHANGE_VERSION } from '~/internals/constants';
import { NEXT_WINDOW_HISTORY_SUPPORT_VERSION } from '~/internals/constants';

import { shouldUseVirtualRouting } from '../next';

Expand All @@ -23,17 +23,17 @@ describe('shouldUseVirtualRouting', () => {

expect(shouldUseVirtualRouting()).toBe(false);
});
it('should return true if version is lower than NEXT_ROUTING_CHANGE_VERSION', () => {
it('should return true if version is lower than NEXT_WINDOW_HISTORY_SUPPORT_VERSION', () => {
windowSpy.mockReturnValue({ next: { version: '14.0.0' } });

expect(shouldUseVirtualRouting()).toBe(true);
});
it('should return false if version is NEXT_ROUTING_CHANGE_VERSION', () => {
windowSpy.mockReturnValue({ next: { version: NEXT_ROUTING_CHANGE_VERSION } });
windowSpy.mockReturnValue({ next: { version: NEXT_WINDOW_HISTORY_SUPPORT_VERSION } });

expect(shouldUseVirtualRouting()).toBe(false);
});
it('should return false if version is higher than NEXT_ROUTING_CHANGE_VERSION', () => {
it('should return false if version is higher than NEXT_WINDOW_HISTORY_SUPPORT_VERSION', () => {
windowSpy.mockReturnValue({ next: { version: '14.6.0' } });

expect(shouldUseVirtualRouting()).toBe(false);
Expand Down
4 changes: 2 additions & 2 deletions packages/elements/src/internals/machines/utils/next.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NEXT_ROUTING_CHANGE_VERSION } from '~/internals/constants';
import { NEXT_WINDOW_HISTORY_SUPPORT_VERSION } from '~/internals/constants';

export function shouldUseVirtualRouting() {
if (typeof window === 'undefined') {
Expand All @@ -9,5 +9,5 @@ export function shouldUseVirtualRouting() {
return false;
}

return window.next.version < NEXT_ROUTING_CHANGE_VERSION;
return window.next.version < NEXT_WINDOW_HISTORY_SUPPORT_VERSION;
}
15 changes: 11 additions & 4 deletions packages/elements/src/react/router/next.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
import { usePathname, useRouter, useSearchParams } from 'next/navigation';

import { NEXT_WINDOW_HISTORY_SUPPORT_VERSION } from '~/internals/constants';

import type { ClerkHostRouter } from './router';

/**
* Framework specific router integrations
* Clerk router integration with Next.js's router.
*/

export const useNextRouter = (): ClerkHostRouter => {
const router = useRouter();
const pathname = usePathname();
const searchParams = 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 {
push: (path: string) => router.push(path),
replace: (path: string) => router.replace(path),
push: (path: string) => (canUseWindowHistoryAPIs ? window.history.pushState(null, '', path) : router.push(path)),
replace: (path: string) =>
canUseWindowHistoryAPIs ? window.history.replaceState(null, '', path) : router.replace(path),
pathname: () => pathname,
searchParams: () => searchParams,
};
Expand Down

0 comments on commit 71319f1

Please sign in to comment.