Skip to content
Merged
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
9 changes: 9 additions & 0 deletions .changeset/pretty-scissors-thank.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@clerk/clerk-js': major
'@clerk/clerk-react': major
'@clerk/types': patch
---

Drop `redirectToHome` redirect method in favour of `redirectToAfterSignUp` or `redirectToAfterSignIn`.

When the `<SignIn/>` and `<SignUp/>` components are rendered while a user is already logged in, they will now redirect to the configured `afterSignIn` and `afterSignUp` URLs, respectively. Previously, the redirect URL was set to the home URL configured in the dashboard.
28 changes: 14 additions & 14 deletions packages/clerk-js/src/core/clerk.redirects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ describe('Clerk singleton - Redirects', () => {
mockNavigate = jest.fn((to: string) => Promise.resolve(to));
});

describe('.redirectTo(SignUp|SignIn|UserProfile|Home|CreateOrganization|OrganizationProfile)', () => {
describe('.redirectTo(SignUp|SignIn|UserProfile|AfterSignIn|AfterSignUp|CreateOrganization|OrganizationProfile)', () => {
let clerkForProductionInstance: Clerk;
let clerkForDevelopmentInstance: Clerk;

Expand Down Expand Up @@ -152,12 +152,20 @@ describe('Clerk singleton - Redirects', () => {
expect(mockNavigate).toHaveBeenNthCalledWith(2, '/user-profile');
});

it('redirects to home', async () => {
await clerkForProductionInstance.redirectToHome();
expect(mockNavigate).toHaveBeenNthCalledWith(1, '/home');
it('redirects to afterSignUp', async () => {
await clerkForProductionInstance.redirectToAfterSignUp();
expect(mockNavigate).toHaveBeenNthCalledWith(1, '/');

await clerkForDevelopmentInstance.redirectToHome();
expect(mockNavigate).toHaveBeenNthCalledWith(2, '/home');
await clerkForDevelopmentInstance.redirectToAfterSignUp();
expect(mockNavigate).toHaveBeenNthCalledWith(2, '/');
});

it('redirects to afterSignIn', async () => {
await clerkForProductionInstance.redirectToAfterSignIn();
expect(mockNavigate).toHaveBeenNthCalledWith(1, '/');

await clerkForDevelopmentInstance.redirectToAfterSignIn();
expect(mockNavigate).toHaveBeenNthCalledWith(2, '/');
});

it('redirects to create organization', async () => {
Expand Down Expand Up @@ -242,14 +250,6 @@ describe('Clerk singleton - Redirects', () => {
expect(mockHref).toHaveBeenNthCalledWith(2, 'http://another-test.host/user-profile#__clerk_db_jwt[deadbeef]');
});

it('redirects to home', async () => {
await clerkForProductionInstance.redirectToHome();
expect(mockHref).toHaveBeenNthCalledWith(1, 'http://another-test.host/home');

await clerkForDevelopmentInstance.redirectToHome();
expect(mockHref).toHaveBeenNthCalledWith(2, 'http://another-test.host/home#__clerk_db_jwt[deadbeef]');
});

it('redirects to create organization', async () => {
await clerkForProductionInstance.redirectToCreateOrganization();
expect(mockHref).toHaveBeenNthCalledWith(1, 'http://another-test.host/create-organization');
Expand Down
41 changes: 37 additions & 4 deletions packages/clerk-js/src/core/clerk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,8 @@ export class Clerk implements ClerkInterface {
public openSignIn = (props?: SignInProps): void => {
this.assertComponentsReady(this.#componentControls);
if (sessionExistsAndSingleSessionModeEnabled(this, this.#environment) && this.#instanceType === 'development') {
return console.info(warnings.cannotOpenSignUpOrSignUp);
console.info(warnings.cannotOpenSignUpOrSignUp);
return;
}
void this.#componentControls
.ensureMounted({ preloadHint: 'SignIn' })
Expand Down Expand Up @@ -372,7 +373,8 @@ export class Clerk implements ClerkInterface {
public openOrganizationProfile = (props?: OrganizationProfileProps): void => {
this.assertComponentsReady(this.#componentControls);
if (noOrganizationExists(this) && this.#instanceType === 'development') {
return console.info(warnings.cannotOpenOrgProfile);
console.info(warnings.cannotOpenOrgProfile);
return;
}
void this.#componentControls
.ensureMounted({ preloadHint: 'OrganizationProfile' })
Expand Down Expand Up @@ -442,6 +444,10 @@ export class Clerk implements ClerkInterface {

public mountUserProfile = (node: HTMLDivElement, props?: UserProfileProps): void => {
this.assertComponentsReady(this.#componentControls);
if (noUserExists(this) && this.#instanceType === 'development') {
console.info(warnings.cannotRenderComponentWhenUserDoesNotExist);
return;
}
void this.#componentControls.ensureMounted({ preloadHint: 'UserProfile' }).then(controls =>
controls.mountComponent({
name: 'UserProfile',
Expand All @@ -465,6 +471,10 @@ export class Clerk implements ClerkInterface {

public mountOrganizationProfile = (node: HTMLDivElement, props?: OrganizationProfileProps) => {
this.assertComponentsReady(this.#componentControls);
if (noOrganizationExists(this) && this.#instanceType === 'development') {
console.info(warnings.cannotRenderComponentWhenOrgDoesNotExist);
return;
}
void this.#componentControls.ensureMounted({ preloadHint: 'OrganizationProfile' }).then(controls =>
controls.mountComponent({
name: 'OrganizationProfile',
Expand Down Expand Up @@ -736,6 +746,22 @@ export class Clerk implements ClerkInterface {
return this.buildUrlWithAuth(this.#environment.displayConfig.homeUrl);
}

public buildAfterSignInUrl(): string {
if (!this.#options.afterSignInUrl) {
return '/';
}

return this.buildUrlWithAuth(this.#options.afterSignInUrl);
}

public buildAfterSignUpUrl(): string {
if (!this.#options.afterSignUpUrl) {
return '/';
}

return this.buildUrlWithAuth(this.#options.afterSignUpUrl);
}

public buildCreateOrganizationUrl(): string {
if (!this.#environment || !this.#environment.displayConfig) {
return '';
Expand Down Expand Up @@ -812,9 +838,16 @@ export class Clerk implements ClerkInterface {
return;
};

public redirectToHome = async (): Promise<unknown> => {
public redirectToAfterSignIn = async (): Promise<unknown> => {
if (inBrowser()) {
return this.navigate(this.buildAfterSignInUrl());
}
return;
};

public redirectToAfterSignUp = async (): Promise<unknown> => {
if (inBrowser()) {
return this.navigate(this.buildHomeUrl());
return this.navigate(this.buildAfterSignUpUrl());
}
return;
};
Expand Down
8 changes: 6 additions & 2 deletions packages/clerk-js/src/core/warnings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ const formatWarning = (msg: string) => {
const warnings = {
cannotRenderComponentWhenSessionExists:
'The <SignUp/> and <SignIn/> components cannot render when a user is already signed in, unless the application allows multiple sessions. Since a user is signed in and this application only allows a single session, Clerk is redirecting to the Home URL instead.',
cannotRenderSignUpComponentWhenSessionExists:
'The <SignUp/> component cannot render when a user is already signed in, unless the application allows multiple sessions. Since a user is signed in and this application only allows a single session, Clerk is redirecting to the value setted in `afterSignUp` URL instead.',
cannotRenderSignInComponentWhenSessionExists:
'The <SignIn/> component cannot render when a user is already signed in, unless the application allows multiple sessions. Since a user is signed in and this application only allows a single session, Clerk is redirecting to the `afterSignIn` URL instead.',
cannotRenderComponentWhenUserDoesNotExist:
'<UserProfile/> cannot render unless a user is signed in. Since no user is signed in, Clerk is redirecting to the Home URL instead. (This notice only appears in development.)',
cannotRenderComponentWhenOrgDoesNotExist: `<OrganizationProfile/> cannot render unless an organization is active. Since no organization is currently active, Clerk is redirecting to the Home URL instead.`,
'<UserProfile/> cannot render unless a user is signed in. Since no user is signed in, this is no-op.',
cannotRenderComponentWhenOrgDoesNotExist: `<OrganizationProfile/> cannot render unless an organization is active. Since no organization is currently active, this is no-op.`,
cannotOpenOrgProfile:
'The OrganizationProfile cannot render unless an organization is active. Since no organization is currently active, this is no-op.',
cannotOpenUserProfile:
Expand Down
43 changes: 43 additions & 0 deletions packages/clerk-js/src/ui/common/__tests__/withRedirect.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';

import { render } from '../../../testUtils';
import { bindCreateFixtures } from '../../utils/test/createFixtures';
import { withRedirect } from '../withRedirect';

const { createFixtures } = bindCreateFixtures('SignIn');

describe('withRedirect', () => {
it('redirects to the redirect url provided when condition is met', async () => {
const { wrapper, fixtures } = await createFixtures(f => {
f.withUser({});
});

const WithHOC = withRedirect(
() => <></>,
() => true,
() => '/',
'Redirecting to /',
);

render(<WithHOC />, { wrapper });

expect(fixtures.router.navigate).toHaveBeenCalledWith('/');
});

it('does no redirects to the redirect url provided when the condition is not met', async () => {
const { wrapper, fixtures } = await createFixtures(f => {
f.withUser({});
});

const WithHOC = withRedirect(
() => <></>,
() => false,
() => '/',
'Redirecting to /',
);

render(<WithHOC />, { wrapper });

expect(fixtures.router.navigate).not.toHaveBeenCalledWith('/');
});
});
102 changes: 0 additions & 102 deletions packages/clerk-js/src/ui/common/__tests__/withRedirectToHome.test.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion packages/clerk-js/src/ui/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export * from './Gate';
export * from './InfiniteListSpinner';
export * from './redirects';
export * from './verification';
export * from './withRedirectToHome';
export * from './withRedirect';
export * from './SSOCallback';
export * from './EmailLinkVerify';
export * from './EmailLinkStatusCard';
Expand Down
Loading