Skip to content

Commit

Permalink
feat(clerk-js,types): Introduce internal Gate component
Browse files Browse the repository at this point in the history
  • Loading branch information
panteliselef committed Oct 6, 2023
1 parent 4c48269 commit da0696a
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 4 deletions.
65 changes: 65 additions & 0 deletions packages/clerk-js/src/ui/common/Gate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import type { IsAuthorized } from '@clerk/types';
import type { ComponentType, PropsWithChildren, ReactNode } from 'react';
import React, { useEffect } from 'react';

import { useCoreSession } from '../contexts';
import { useFetch } from '../hooks';
import { useRouter } from '../router';

type GateParams = Parameters<IsAuthorized>[0];
type GateProps = PropsWithChildren<
GateParams & {
fallback?: ReactNode;
redirectTo?: string;
}
>;

export const useGate = (params: GateParams) => {
const { isAuthorized } = useCoreSession();
const { data: isAuthorizedUser } = useFetch(isAuthorized, params);

return {
isAuthorizedUser,
};
};

export const Gate = (gateProps: GateProps) => {
const { children, fallback, redirectTo, ...restAuthorizedParams } = gateProps;

const { isAuthorizedUser } = useGate(restAuthorizedParams);

const { navigate } = useRouter();

useEffect(() => {
// wait for promise to resolve
if (typeof isAuthorizedUser === 'boolean' && !isAuthorizedUser && redirectTo) {
void navigate(redirectTo);
}
}, [isAuthorizedUser, redirectTo]);

// wait for promise to resolve
if (typeof isAuthorizedUser === 'boolean' && !isAuthorizedUser && fallback) {
return <>{fallback}</>;
}

if (isAuthorizedUser) {
return <>{children}</>;
}

return null;
};

export function withGate<P>(Component: ComponentType<P>, gateProps: GateProps): React.ComponentType<P> {
const displayName = Component.displayName || Component.name || 'Component';
const HOC = (props: P) => {
return (
<Gate {...gateProps}>
<Component {...(props as any)} />
</Gate>
);
};

HOC.displayName = `withGate(${displayName})`;

return HOC;
}
1 change: 1 addition & 0 deletions packages/clerk-js/src/ui/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './BlockButtons';
export * from './constants';
export * from './CalloutWithAction';
export * from './forms';
export * from './Gate';
export * from './InfiniteListSpinner';
export * from './redirects';
export * from './verification';
Expand Down
8 changes: 4 additions & 4 deletions packages/clerk-js/src/ui/hooks/useFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ export const useFetch = <T>(
requestStatus.setLoading();
fetcherRef
.current(params)
.then(domain => {
.then(result => {
requestStatus.setIdle();
if (domain) {
setData({ ...domain });
callbacks?.onSuccess?.({ ...domain });
if (typeof result !== 'undefined') {
setData(typeof result === 'object' ? { ...result } : result);
callbacks?.onSuccess?.(typeof result === 'object' ? { ...result } : result);
}
})
.catch(() => {
Expand Down

0 comments on commit da0696a

Please sign in to comment.