Skip to content

Instantly share code, notes, and snippets.

@zackdotcomputer
Created March 21, 2022 12:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zackdotcomputer/278344333895d8ef452cff24750f2d66 to your computer and use it in GitHub Desktop.
Save zackdotcomputer/278344333895d8ef452cff24750f2d66 to your computer and use it in GitHub Desktop.
Fix Clerk Unmount on Reauth
import { AuthProvider, useAuth } from "@redwoodjs/auth";
import { ClerkProvider, useClerk, useUser as useClerkUser } from "@clerk/clerk-react";
import { FatalErrorBoundary, RedwoodProvider } from "@redwoodjs/web";
import { RedwoodApolloProvider } from "@redwoodjs/web/apollo";
import FatalErrorPage from "src/pages/FatalErrorPage";
import Routes from "src/Routes";
import "./index.css";
import { navigate } from "@redwoodjs/router";
import { PropsWithChildren, useEffect, useState } from "react";
/** BEGIN Clerk Auth Setup */
// Replace Redwood's <AuthProvider> with the <ClerkAuthProvider>.
//
// You can set user roles in a "roles" array on the public metadata in Clerk.
//
// Also, you need to add two env variables: CLERK_FRONTEND_API_URL for web and
// CLERK_API_KEY for api, with the frontend api host and api key, respectively,
// both from your Clerk.dev dashboard.
//
// Lastly, be sure to add the key "CLERK_FRONTEND_API_URL" in your app's redwood.toml
// [web] config "includeEnvironmentVariables" setting.
// This component holds off rendering its children until the clerk client has loaded once.
const ClerkAuthConsumer = ({ children }: PropsWithChildren<unknown>) => {
const clerk = useClerk();
const [hasFirstLoaded, setHasFirstLoaded] = useState(false);
useEffect(() => {
if (clerk.client) {
setHasFirstLoaded(true);
}
}, [clerk.client]);
if (!hasFirstLoaded) {
return null;
}
return <>{children}</>;
};
// This component triggers a reauth at the Redwood level whenever Clerk's auth state changes.
const ClerkAuthListener = ({ children }: PropsWithChildren<unknown>) => {
const { isSignedIn, user } = useClerkUser();
const { reauthenticate } = useAuth();
useEffect(() => {
reauthenticate();
}, [isSignedIn, user, reauthenticate]);
return <>{children}</>;
};
const ClerkAuthProvider = ({ children }) => {
const frontendApi = process.env.CLERK_FRONTEND_API_URL;
if (!frontendApi) {
throw new Error("Need to define env variable CLERK_FRONTEND_API_URL");
}
return (
<ClerkProvider frontendApi={frontendApi} navigate={(to) => navigate(to)}>
<ClerkAuthConsumer>
<AuthProvider type="clerk">
<ClerkAuthListener>{children}</ClerkAuthListener>
</AuthProvider>
</ClerkAuthConsumer>
</ClerkProvider>
);
};
/** END Clerk Auth Setup */
const App = () => (
<FatalErrorBoundary page={FatalErrorPage}>
<RedwoodProvider titleTemplate="%PageTitle | %AppTitle">
<ClerkAuthProvider>
<RedwoodApolloProvider>
<Routes />
</RedwoodApolloProvider>
</ClerkAuthProvider>
</RedwoodProvider>
</FatalErrorBoundary>
);
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment