I am trying to use Auth0's useAuth0()
hook to retrieve getAccessTokenSilently()
in a react-router action, so I can get an access token to make a protected API call to my service to execute the action.
Based on this past similar question it appears the way to do this is to call the hook in the parent App component then pass it as a function to any loaders or actions that need it. Cool, sounds great!
Unfortunately TypeScript flat out refuses to allow this.
I've tried creating a custom type that extends ActionFunctionArgs so TypeScript knows there will be another property, but that just results in errors about how my action function can't be assigned to the action: property of the route.
Has anyone ever done this successfully? How do you use an authentication hook inside an action in TypeScript? Is there another way this should be done?
Edit: here's code.
main.tsx:
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
appAction.mts (the action I want to use authentication stuff in):
import { ActionFunction } from "react-router-dom";
export const appAction: ActionFunction =
({ getAccessTokenSilently }) =>
async ({ request, params }) => {
const token = await getAccessTokenSilently();
const formData = await request.formData();
const intent = formData.get("intent");
// Do something with the token here when calling an API.
};
App.tsx:
const App: React.FC = () => {
const { getAccessTokenSilently } = useAuth0();
const router = createBrowserRouter([
{
element: <Auth0ProviderLayout />,
errorElement: <ErrorPage />,
children: [
{
path: "/verifier",
element: <ProtectedRoute component={Verifier} />,
loader: activeFlightPlansLoader,
action: appAction({ getAccessTokenSilently }),
... etc
Typescript has many issues with this.
appAction
function definition it says:"Property 'getAccessTokenSilently' does not exist on type 'ActionFunctionArgs'"
appAction
to the action
property when creating the routes it says:Type 'DataFunctionValue | Promise' is not
assignable to type 'ActionFunction | undefined'. Type 'null' is not
assignable to type 'ActionFunction | undefined'
and:
Argument of type '{ getAccessTokenSilently: { (options: GetTokenSilentlyOptions & { detailedResponse: true; }): Promise; (options?: GetTokenSilentlyOptions | undefined): Promise<...>; (options: GetTokenSilentlyOptions): Promise<...>; }; }' is not assignable to parameter of type 'ActionFunctionArgs'. Object literal may only specify known properties, and 'getAccessTokenSilently' does not exist in type 'ActionFunctionArgs'.
The function appAction
is not of type ActionFunction
, but is a function that returns an action function of that type.
import type { ActionFunction } from "react-router-dom";
interface AppAction {
getAccessTokenSilently: () => Promise<string>; // <-- or whatever this needs to be
}
const appAction = ({
getAccessTokenSilently
}: AppAction): ActionFunction => async ({ request, params }) => {
const token = await getAccessTokenSilently();
const formData = await request.formData();
const intent = formData.get("intent");
// Do something with the token here when calling an API.
};