如何在React Router v6.4的loader和action中获取Auth0访问令牌?
如何在React Router v6.4的
actions和loaders中获取Auth0访问令牌以调用受保护API? 我尝试将getAccessTokenSilently()方法柯里化到loader中,但无法在组件外部调用useAuth0()钩子(我的路由是按照React Router文档建议在组件外部创建的)。同样,也无法在loader内部调用useAuth0(),因为它不是组件。
我尝试将路由放到组件内部(把路由移到<App/>组件中),但useAuth0()报错,提示必须在Auth0Provider内部调用。
官方的Auth0 React Router v6指南尚未更新到使用createBrowserRouter,且其安全API示例未使用loaders。
这似乎是React Router v6.4应用中的基础需求,但我始终找不到相关示例。肯定有人解决过这个问题吧?
更新:问题已解决!以下是完整的可运行代码版本。
Auth0ProviderWithNavigate.tsx
interface Auth0ProviderWithNavigateProps { children: React.ReactNode; } export const Auth0ProviderWithNavigate = ({ children, }: Auth0ProviderWithNavigateProps) => { if ( !( ENV.VITE_AUTH0_DOMAIN && ENV.VITE_AUTH0_CLIENT_ID && ENV.VITE_AUTH0_CALLBACK_URL ) ) { return null; } return ( <Auth0Provider domain={ENV.VITE_AUTH0_DOMAIN} clientId={ENV.VITE_AUTH0_CLIENT_ID} authorizationParams={{ redirect_uri: ENV.VITE_AUTH0_CALLBACK_URL, }} > {children} </Auth0Provider> ); };
AuthenticationGuard.tsx
import { withAuthenticationRequired } from "@auth0/auth0-react"; import { PageLoader } from "./PageLoader"; interface AuthenticationGuardProps { component: React.ComponentType<object>; } export const AuthenticationGuard = ({ component, }: AuthenticationGuardProps) => { const Component = withAuthenticationRequired(component, { onRedirecting: () => <PageLoader />, }); return <Component />; };
main.tsx
const root = document.getElementById("root"); root && ReactDOM.createRoot(root).render( <React.StrictMode> <AppContextProvider> <Auth0ProviderWithNavigate> <AppTheme> <App /> </AppTheme> </Auth0ProviderWithNavigate> </AppContextProvider> </React.StrictMode> );
App.tsx
const App = () => { const { getAccessTokenSilently } = useAuth0(); const router = useMemo(() => { return createBrowserRouter([ { children: [ { path: "/", element: <WelcomePage />, errorElement: <ErrorPage />, }, { children: [ { id: "edct", path: "/edct", element: <AuthenticationGuard component={Edct} />, errorElement: <ErrorPage />, loader: AirportCodesLoader({ getAccessTokenSilently }), }, ], }, ], }, ]); }, [getAccessTokenSilently]); return <RouterProvider router={router} />; }; export default App;
AirportCodesLoader.tsx
import { ActionFunction } from "react-router"; const cleanCodes = (codes: string | null): string | null => { if (!codes) { return null; } return codes .split(",") .map((code) => code.trim()) .join(","); }; interface AppLoader { getAccessTokenSilently: () => Promise<string>; } export const AirportCodesLoader = ({ getAccessTokenSilently }: AppLoader): ActionFunction => async ({ request }) => { const url = new URL(request.url); console.log(await getAccessTokenSilently()); return { departureCodes: cleanCodes(url.searchParams.get("departureCodes")) ?? "", arrivalCodes: cleanCodes(url.searchParams.get("arrivalCodes")) ?? "", }; };
内容的提问来源于stack exchange,提问作者Neil E
相关产品推荐
相关产品推荐

