Skip to content

feat(clerk-react): Support for fallback prop #4723

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

Merged
merged 13 commits into from
Dec 20, 2024
10 changes: 10 additions & 0 deletions .changeset/serious-stingrays-learn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@clerk/clerk-react': minor
---

Adds support for a `fallback` prop on Clerk's components. This allows rendering of a placeholder element while Clerk's components are mounting. Use this to help mitigate layout shift when using Clerk's components. Example usage:


```tsx
<SignIn fallback={<LoadingSkeleton />} />
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { CreateOrganization } from '@clerk/nextjs';

export default function Page() {
return (
<div>
<CreateOrganization fallback={<>Loading create organization</>} />
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { OrganizationList } from '@clerk/nextjs';

export default function Page() {
return (
<div>
<OrganizationList fallback={<>Loading organization list</>} />
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { OrganizationProfile } from '@clerk/nextjs';

export default function Page() {
return (
<div>
<OrganizationProfile
routing='hash'
fallback={<>Loading organization profile</>}
/>
</div>
);
}
5 changes: 3 additions & 2 deletions integration/templates/next-app-router/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { SignedIn, SignedOut, SignIn, UserButton, Protect } from '@clerk/nextjs';
import { SignedIn, SignedOut, SignIn, UserButton, Protect, OrganizationSwitcher } from '@clerk/nextjs';
import Link from 'next/link';
import { ClientId } from './client-id';

export default function Home() {
return (
<main>
<UserButton />
<UserButton fallback={<>Loading user button</>} />
<OrganizationSwitcher fallback={<>Loading organization switcher</>} />
<ClientId />
<SignedIn>SignedIn</SignedIn>
<SignedOut>SignedOut</SignedOut>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default function Page() {
routing={'path'}
path={'/sign-in'}
signUpUrl={'/sign-up'}
fallback={<>Loading sign in</>}
__experimental={{
combinedProps: {},
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default function Page() {
routing={'path'}
path={'/sign-up'}
signInUrl={'/sign-in'}
fallback={<>Loading sign up</>}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { OrganizationSwitcher } from '@clerk/nextjs';

export default function Page() {
return <OrganizationSwitcher hidePersonal={true} />;
return (
<OrganizationSwitcher
hidePersonal={true}
fallback={<>Loading organization switcher</>}
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { UserButton } from '@clerk/nextjs';

export default function Page() {
return (
<div>
<UserButton fallback={<>Loading user button</>} />
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { UserProfile } from '@clerk/nextjs';
export default function Page() {
return (
<div>
<UserProfile />
<UserProfile fallback={<>Loading user profile</>} />
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Waitlist } from '@clerk/nextjs';

export default function Page() {
return (
<div>
<Waitlist fallback={<>Loading waitlist</>} />
</div>
);
}
2 changes: 1 addition & 1 deletion integration/templates/react-vite/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ function App() {
return (
<main>
<UserButton afterSignOutUrl={'/'} />
<OrganizationSwitcher />
<OrganizationSwitcher fallback={<>Loading organization switcher</>} />
<ClientId />
<SignedOut>SignedOut</SignedOut>
<SignedIn>SignedIn</SignedIn>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { CreateOrganization } from '@clerk/clerk-react';

export default function Page() {
return (
<div>
<CreateOrganization fallback={<>Loading create organization</>} />
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function Page1() {
export default function Page() {
return (
<PageContextProvider>
<UserButton>
<UserButton fallback={<>Loading user button</>}>
<UserButton.UserProfilePage
label={'Page 1'}
labelIcon={<p data-label-icon={'page-1'}>🙃</p>}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ function Page1() {
export default function Page() {
return (
<PageContextProvider>
<UserProfile path={'/custom-user-profile'}>
<UserProfile
fallback={<>Loading user profile</>}
path={'/custom-user-profile'}
>
<UserProfile.Page
label={'Page 1'}
labelIcon={<p data-label-icon={'page-1'}>🙃</p>}
Expand Down
25 changes: 25 additions & 0 deletions integration/templates/react-vite/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import UserProfile from './user';
import UserProfileCustom from './custom-user-profile';
import UserButtonCustom from './custom-user-button';
import UserButtonCustomTrigger from './custom-user-button-trigger';
import UserButton from './user-button';
import Waitlist from './waitlist';
import OrganizationProfile from './organization-profile';
import OrganizationList from './organization-list';
import CreateOrganization from './create-organization';

const Root = () => {
const navigate = useNavigate();
Expand Down Expand Up @@ -53,6 +58,10 @@ const router = createBrowserRouter([
path: '/user/*',
element: <UserProfile />,
},
{
path: '/user-button',
element: <UserButton />,
},
{
path: '/protected',
element: <Protected />,
Expand All @@ -69,6 +78,22 @@ const router = createBrowserRouter([
path: '/custom-user-button-trigger',
element: <UserButtonCustomTrigger />,
},
{
path: '/waitlist',
element: <Waitlist />,
},
{
path: '/organization-profile',
element: <OrganizationProfile />,
},
{
path: '/organization-list',
element: <OrganizationList />,
},
{
path: '/create-organization',
element: <CreateOrganization />,
},
],
},
]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { OrganizationList } from '@clerk/clerk-react';

export default function Page() {
return (
<div>
<OrganizationList fallback={<>Loading organization list</>} />
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { OrganizationProfile } from '@clerk/clerk-react';

export default function Page() {
return (
<div>
<OrganizationProfile
routing='hash'
fallback={<>Loading organization profile</>}
/>
</div>
);
}
1 change: 1 addition & 0 deletions integration/templates/react-vite/src/sign-in/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export default function Page() {
<SignIn
path={'/sign-in'}
signUpUrl={'/sign-up'}
fallback={<>Loading sign in</>}
/>
</div>
);
Expand Down
1 change: 1 addition & 0 deletions integration/templates/react-vite/src/sign-up/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export default function Page() {
<SignUp
path={'/sign-up'}
signInUrl={'/sign-in'}
fallback={<>Loading sign up</>}
/>
</div>
);
Expand Down
9 changes: 9 additions & 0 deletions integration/templates/react-vite/src/user-button/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { UserButton } from '@clerk/clerk-react';

export default function Page() {
return (
<div>
<UserButton fallback={<>Loading user button</>} />
</div>
);
}
5 changes: 4 additions & 1 deletion integration/templates/react-vite/src/user/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { UserProfile } from '@clerk/clerk-react';
export default function Page() {
return (
<div>
<UserProfile path={'/user'} />
<UserProfile
path={'/user'}
fallback={<>Loading user profile</>}
/>
</div>
);
}
9 changes: 9 additions & 0 deletions integration/templates/react-vite/src/waitlist/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Waitlist } from '@clerk/clerk-react';

export default function Page() {
return (
<div>
<Waitlist fallback={<>Loading waitlist</>} />
</div>
);
}
4 changes: 2 additions & 2 deletions integration/testUtils/appPageObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const createAppPageObject = (testArgs: { page: Page }, app: Application)
// do not fail the test if interstitial is returned (401)
}
},
goToRelative: (path: string, opts: { searchParams?: URLSearchParams; timeout?: number } = {}) => {
goToRelative: (path: string, opts: { waitUntil?: any; searchParams?: URLSearchParams; timeout?: number } = {}) => {
let url: URL;

try {
Expand All @@ -35,7 +35,7 @@ export const createAppPageObject = (testArgs: { page: Page }, app: Application)
if (opts.searchParams) {
url.search = opts.searchParams.toString();
}
return page.goto(url.toString(), { timeout: opts.timeout ?? 20000 });
return page.goto(url.toString(), { timeout: opts.timeout ?? 20000, waitUntil: opts.waitUntil });
},
waitForClerkJsLoaded: async () => {
return page.waitForFunction(() => {
Expand Down
Loading
Loading