diff --git a/.changeset/wicked-worms-draw.md b/.changeset/wicked-worms-draw.md new file mode 100644 index 00000000000..3af49c5eb69 --- /dev/null +++ b/.changeset/wicked-worms-draw.md @@ -0,0 +1,5 @@ +--- +'@clerk/remix': patch +--- + +Automatically infer the path for where the component is mounted. diff --git a/packages/remix/src/client/uiComponents.tsx b/packages/remix/src/client/uiComponents.tsx index d3cd7f457c0..6534dc0c5d8 100644 --- a/packages/remix/src/client/uiComponents.tsx +++ b/packages/remix/src/client/uiComponents.tsx @@ -15,7 +15,7 @@ import type { } from '@clerk/types'; import React from 'react'; -import { useClerkRemixOptions } from './RemixOptionsContext'; +import { usePathnameWithoutSplatRouteParams } from './usePathnameWithoutSplatRouteParams'; // The assignment of UserProfile with BaseUserProfile props is used // to support the CustomPage functionality (eg UserProfile.Page) @@ -23,13 +23,15 @@ import { useClerkRemixOptions } from './RemixOptionsContext'; // "The inferred type of 'UserProfile' cannot be named without a reference to ..." export const UserProfile: typeof BaseUserProfile = Object.assign( (props: UserProfileProps) => { - return ; + const path = usePathnameWithoutSplatRouteParams(); + return ; }, { ...BaseUserProfile }, ); export const CreateOrganization = (props: CreateOrganizationProps) => { - return ; + const path = usePathnameWithoutSplatRouteParams(); + return ; }; // The assignment of OrganizationProfile with BaseOrganizationProfile props is used @@ -38,17 +40,18 @@ export const CreateOrganization = (props: CreateOrganizationProps) => { // "The inferred type of 'OrganizationProfile' cannot be named without a reference to ..." export const OrganizationProfile: typeof BaseOrganizationProfile = Object.assign( (props: OrganizationProfileProps) => { - return ; + const path = usePathnameWithoutSplatRouteParams(); + return ; }, { ...BaseOrganizationProfile }, ); export const SignIn = (props: SignInProps) => { - const { signInUrl } = useClerkRemixOptions(); - return ; + const path = usePathnameWithoutSplatRouteParams(); + return ; }; export const SignUp = (props: SignUpProps) => { - const { signUpUrl } = useClerkRemixOptions(); - return ; + const path = usePathnameWithoutSplatRouteParams(); + return ; }; diff --git a/packages/remix/src/client/usePathnameWithoutSplatRouteParams.tsx b/packages/remix/src/client/usePathnameWithoutSplatRouteParams.tsx new file mode 100644 index 00000000000..97cb85ca4f7 --- /dev/null +++ b/packages/remix/src/client/usePathnameWithoutSplatRouteParams.tsx @@ -0,0 +1,18 @@ +import { useLocation, useParams } from '@remix-run/react'; + +export const usePathnameWithoutSplatRouteParams = () => { + const params = useParams(); + const { pathname } = useLocation(); + + // Get the splat route params + // Remix store splat route params in an object with a key of '*' + // If there are no splat route params, we fallback to an empty string + const splatRouteParam = params['*'] || ''; + + // Remove the splat route param from the pathname + // so we end up with the pathname where the components are mounted at + // eg /user/123/profile/security will return /user/123/profile as the path + const path = pathname.replace(splatRouteParam, '').replace(/\/$/, '').replace(/^\//, '').trim(); + + return `/${path}`; +};