You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 13:07:52