-
Notifications
You must be signed in to change notification settings - Fork 461
feat(clerk-react,remix,nextjs): Make path the default routing strategy for NextJS and Remix #2338
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
Changes from all commits
85a5f3e
97a1ea6
cd8ae3a
7ca360e
24c375a
f82b75b
36fa16d
b41d612
563f1e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| --- | ||
| '@clerk/clerk-js': major | ||
| '@clerk/nextjs': major | ||
| '@clerk/clerk-react': major | ||
| '@clerk/remix': major | ||
| --- | ||
|
|
||
| Path-based routing is now the default routing strategy if the `path` prop is filled. Additionally, if the `path` and `routing` props are not filled, an error will be thrown. | ||
| ```jsx | ||
|
|
||
| // Without path or routing props, an error with be thrown | ||
| <UserProfile /> | ||
| <CreateOrganization /> | ||
| <OrganizationProfile /> | ||
| <SignIn /> | ||
| <SignUp /> | ||
|
|
||
| // Alternative #1 | ||
| <UserProfile path="/whatever"/> | ||
| <CreateOrganization path="/whatever"/> | ||
| <OrganizationProfile path="/whatever"/> | ||
| <SignIn path="/whatever"/> | ||
| <SignUp path="/whatever"/> | ||
|
|
||
| // Alternative #2 | ||
| <UserProfile routing="hash_or_virtual"/> | ||
| <CreateOrganization routing="hash_or_virtual"/> | ||
| <OrganizationProfile routing="hash_or_virtual"/> | ||
| <SignIn routing="hash_or_virtual"/> | ||
| <SignUp routing="hash_or_virtual"/> | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,52 +1,52 @@ | ||
| 'use client'; | ||
|
|
||
| import { SignIn as BaseSignIn, SignUp as BaseSignUp } from '@clerk/clerk-react'; | ||
| import type { SignInProps, SignUpProps } from '@clerk/types'; | ||
| import { | ||
| CreateOrganization as BaseCreateOrganization, | ||
| OrganizationProfile as BaseOrganizationProfile, | ||
| SignIn as BaseSignIn, | ||
| SignUp as BaseSignUp, | ||
| UserProfile as BaseUserProfile, | ||
| } from '@clerk/clerk-react'; | ||
| import { useRoutingProps } from '@clerk/clerk-react/internal'; | ||
| import type { | ||
| CreateOrganizationProps, | ||
| OrganizationProfileProps, | ||
| SignInProps, | ||
| SignUpProps, | ||
| UserProfileProps, | ||
| } from '@clerk/types'; | ||
| import React from 'react'; | ||
|
|
||
| import { useClerkNextOptions } from './NextOptionsContext'; | ||
|
|
||
| export { | ||
| CreateOrganization, | ||
| OrganizationList, | ||
| OrganizationProfile, | ||
| OrganizationSwitcher, | ||
| SignInButton, | ||
| SignInWithMetamaskButton, | ||
| SignOutButton, | ||
| SignUpButton, | ||
| UserButton, | ||
| UserProfile, | ||
| } from '@clerk/clerk-react'; | ||
|
|
||
| export const UserProfile = (props: UserProfileProps) => { | ||
| return <BaseUserProfile {...useRoutingProps('UserProfile', props)} />; | ||
| }; | ||
|
|
||
| export const CreateOrganization = (props: CreateOrganizationProps) => { | ||
| return <BaseCreateOrganization {...useRoutingProps('CreateOrganization', props)} />; | ||
| }; | ||
|
|
||
| export const OrganizationProfile = (props: OrganizationProfileProps) => { | ||
| return <BaseOrganizationProfile {...useRoutingProps('OrganizationProfile', props)} />; | ||
| }; | ||
|
|
||
| export const SignIn = (props: SignInProps) => { | ||
| const { signInUrl: repoLevelSignInUrl } = useClerkNextOptions(); | ||
| const path = props.path || repoLevelSignInUrl; | ||
|
|
||
| if (path) { | ||
| <BaseSignIn | ||
| {...props} | ||
| routing='path' | ||
| path={path} | ||
| />; | ||
| } | ||
|
|
||
| return <BaseSignIn {...props} />; | ||
| const { signInUrl } = useClerkNextOptions(); | ||
| return <BaseSignIn {...useRoutingProps('SignIn', props, { path: signInUrl })} />; | ||
| }; | ||
|
|
||
| export const SignUp = (props: SignUpProps) => { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems that you're not using the HOC for the components that are mounted in paths we can infer using the env variables. I feel like we should align this behavior by either:
Do you want to discuss offline for possible solutions? :)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ☝️
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep I thought about that too, but the |
||
| const { signUpUrl: repoLevelSignUpUrl } = useClerkNextOptions(); | ||
| const path = props.path || repoLevelSignUpUrl; | ||
|
|
||
| if (path) { | ||
| return ( | ||
| <BaseSignUp | ||
| {...props} | ||
| routing='path' | ||
| path={path} | ||
| /> | ||
| ); | ||
| } | ||
|
|
||
| return <BaseSignUp {...props} />; | ||
| const { signUpUrl } = useClerkNextOptions(); | ||
| return <BaseSignUp {...useRoutingProps('SignUp', props, { path: signUpUrl })} />; | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| import type { RoutingOptions } from '@clerk/types'; | ||
|
|
||
| import { errorThrower } from '../errors/errorThrower'; | ||
| import { noPathProvidedError } from '../errors/messages'; | ||
|
|
||
| export function useRoutingProps<T extends RoutingOptions>( | ||
| componentName: string, | ||
| props: T, | ||
| routingOptions?: RoutingOptions, | ||
| ): T { | ||
| if (!props.path && !props.routing) { | ||
| errorThrower.throw(noPathProvidedError(componentName)); | ||
| } | ||
|
|
||
| if (props.path) { | ||
| return { | ||
| ...routingOptions, | ||
| ...props, | ||
| routing: 'path', | ||
| }; | ||
| } | ||
|
|
||
| return { | ||
| ...routingOptions, | ||
| ...props, | ||
| }; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| export { setErrorThrowerOptions } from './errors/errorThrower'; | ||
| export { MultisessionAppSupport } from './components/controlComponents'; | ||
| export { useRoutingProps } from './hooks/useRoutingProps'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,37 +1,40 @@ | ||
| import { SignIn as BaseSignIn, SignUp as BaseSignUp } from '@clerk/clerk-react'; | ||
| import type { SignInProps, SignUpProps } from '@clerk/types'; | ||
| import { | ||
| CreateOrganization as BaseCreateOrganization, | ||
| OrganizationProfile as BaseOrganizationProfile, | ||
| SignIn as BaseSignIn, | ||
| SignUp as BaseSignUp, | ||
| UserProfile as BaseUserProfile, | ||
| } from '@clerk/clerk-react'; | ||
| import { useRoutingProps } from '@clerk/clerk-react/internal'; | ||
| import type { | ||
| CreateOrganizationProps, | ||
| OrganizationProfileProps, | ||
| SignInProps, | ||
| SignUpProps, | ||
| UserProfileProps, | ||
| } from '@clerk/types'; | ||
| import React from 'react'; | ||
|
|
||
| import { useClerkRemixOptions } from './RemixOptionsContext'; | ||
|
|
||
| export const SignIn = (props: SignInProps) => { | ||
| const { signInUrl } = useClerkRemixOptions(); | ||
| const path = props.path || signInUrl; | ||
| export const UserProfile = (props: UserProfileProps) => { | ||
| return <BaseUserProfile {...useRoutingProps('UserProfile', props)} />; | ||
| }; | ||
|
|
||
| if (path) { | ||
| return ( | ||
| <BaseSignIn | ||
| {...props} | ||
| routing='path' | ||
| path={path} | ||
| /> | ||
| ); | ||
| } | ||
| export const CreateOrganization = (props: CreateOrganizationProps) => { | ||
| return <BaseCreateOrganization {...useRoutingProps('CreateOrganization', props)} />; | ||
| }; | ||
|
|
||
| return <BaseSignIn {...props} />; | ||
| export const OrganizationProfile = (props: OrganizationProfileProps) => { | ||
| return <BaseOrganizationProfile {...useRoutingProps('OrganizationProfile', props)} />; | ||
| }; | ||
|
|
||
| export const SignIn = (props: SignInProps) => { | ||
| const { signInUrl } = useClerkRemixOptions(); | ||
| return <BaseSignIn {...useRoutingProps('SignIn', props, { path: signInUrl })} />; | ||
| }; | ||
|
|
||
| export const SignUp = (props: SignUpProps) => { | ||
| const { signUpUrl } = useClerkRemixOptions(); | ||
| const path = props.path || signUpUrl; | ||
|
|
||
| if (path) { | ||
| return ( | ||
| <BaseSignUp | ||
| routing='path' | ||
| path={path} | ||
| /> | ||
| ); | ||
| } | ||
| return <BaseSignUp {...props} />; | ||
| return <BaseSignUp {...useRoutingProps('SignUp', props, { path: signUpUrl })} />; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,7 +7,7 @@ const OrganizationProfilePage: NextPage = () => { | |
| <div | ||
| style={{ display: 'flex', flexDirection: 'column', gap: '2rem', justifyContent: 'center', alignItems: 'center' }} | ||
| > | ||
| <OrganizationProfile /> | ||
| <OrganizationProfile path='/organization' /> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❓ Will this error on dev time due to missing type?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This error will be shown when the component is being rendered. This is a runtime error |
||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SokratisVidros , @nikosdouvlis i have also added examples in changeset