auth0-developer-hub / spa_react_javascript_hello-world

This JavaScript code sample demonstrates how to implement authentication in a React application that uses React Router 6. You can integrate the Auth0 React SDK with React Router 6 to create route guards in React.
Apache License 2.0
64 stars 86 forks source link

Passing props to the components of ProtectedRoute #1

Closed aorait closed 1 year ago

aorait commented 2 years ago

I am following the instructions here to use Auth0 with react-router-dom V6 and so far I am able to get it working with the basic routes.

Now I am trying to make it work with components which accept props and I not sure how to pass in the props correctly. This is the code for the ProtectedRoute

import React, { ComponentType } from 'react';
import { withAuthenticationRequired } from '@auth0/auth0-react';
import { Loading } from './Loading';

interface ProtectedRouteProps {
  component: ComponentType,
  props: any
}

export const ProtectedRoute: React.FC<ProtectedRouteProps> = ({
  component, props
}) => {
  const Component = withAuthenticationRequired(component, {
    onRedirecting: () => <Loading />,
  });

  return <Component {...props} />;
};

And I am setting up the basic route component as

<Route path="/" element={<ProtectedRoute component={Dashboard} />}/>

My Dashboard element expects a prop of say type string and name testProp. What would be the right way to pass it in? I have tried the following but none of them work correctly.

<Route path="/" element={<ProtectedRoute component={Dashboard} testProp={"test"} />}/>

<Route path="/" element={<ProtectedRoute component={Dashboard} props={{testProp: "test"}} />}/>

Can you please provide an example of how to forward the props to the ProtectedRoute? I am new to react and typescript and I am not able to figure out the right approach for this.

ghost commented 2 years ago

@aorait you can try with a different approach, something called layout route (compound components).

const ProtectedRoute = withAuthenticationRequired(({ children }) => <>{children}</>, {
  onRedirecting: () => <Loading />,
});

and then you can use it like this:

<Route
  path="/"
  element={
    <ProtectedRoute>
      <Dashboard testProp="test" />
    </ProtectedRoute>
  }
/>
ymonye commented 1 year ago

I am following the instructions here to use Auth0 with react-router-dom V6 and so far I am able to get it working with the basic routes.

Now I am trying to make it work with components which accept props and I not sure how to pass in the props correctly. This is the code for the ProtectedRoute

import React, { ComponentType } from 'react';
import { withAuthenticationRequired } from '@auth0/auth0-react';
import { Loading } from './Loading';

interface ProtectedRouteProps {
  component: ComponentType,
  props: any
}

export const ProtectedRoute: React.FC<ProtectedRouteProps> = ({
  component, props
}) => {
  const Component = withAuthenticationRequired(component, {
    onRedirecting: () => <Loading />,
  });

  return <Component {...props} />;
};

And I am setting up the basic route component as

<Route path="/" element={<ProtectedRoute component={Dashboard} />}/>

My Dashboard element expects a prop of say type string and name testProp. What would be the right way to pass it in? I have tried the following but none of them work correctly.

<Route path="/" element={<ProtectedRoute component={Dashboard} testProp={"test"} />}/>

<Route path="/" element={<ProtectedRoute component={Dashboard} props={{testProp: "test"}} />}/>

Can you please provide an example of how to forward the props to the ProtectedRoute? I am new to react and typescript and I am not able to figure out the right approach for this.

Hey, did you ever get this working? I'm getting the same problem

dbritto-dev commented 1 year ago

@ymonye did you try my approach? I use to use that a lot on RR v6

ymonye commented 1 year ago

@ymonye did you try my approach? I use to use that a lot on RR v6

Hey @dbritto-dev, yeah I did (retesting right now), and my page didn't at all load with your example. I also see Auth0 replaced ProtectedGuard with AuthenticationGuard:

https://github.com/auth0-developer-hub/spa_react_javascript_hello-world_react-router-6/blob/main/src/components/authentication-guard.js

My code:

import { withAuthenticationRequired } from "@auth0/auth0-react";
import PageLoader from "../pages/PageLoader";

export const AuthenticationGuard = ({ component, props }) => {
  const Component = withAuthenticationRequired(({children}) => <>{children}</>, {
    onRedirecting: () => (
      <div >
        {"PageLoader"}
      </div>
    ),
  });

  return <Component {...props}/>;
};
ymonye commented 1 year ago

For reference @dbritto-dev, I'm running my Routes the following way: <Route path='/:siteID/history/*' element={<History data={{siteID, stateID, cityID}} customerID={''}/>} />

I'd also brought this up on the Auth0 forums without much success (so far): https://community.auth0.com/t/react-authentication-by-example-react-router-6/96908/6?u=ymonye

dbritto-dev commented 1 year ago

@ymonye that's the code I'm using right now with Vite + RR6 app

import { memo } from 'react';
import { withAuthenticationRequired } from '@auth0/auth0-react';

export const AuthGuard = withAuthenticationRequired(
  memo(({ children }) => <>{children}</>),
  { onRedirecting: () => <div>Loading...</div> },
);

and then you can use it like this:

<Route
  path="/:siteID/history/*"
  element={
    <AuthGuard>
      <History 
        data={{ siteID, stateID, cityID }} 
        customerID={''}
      />
    </AuthGuard>
  }
/>

or like this:

<Route
  element={
    <AuthGuard>
      <Outlet />
    </AuthGuard>
  }
>
  <Route
    path="/:siteID/history/*"
    element={
      <History 
        data={{ siteID, stateID, cityID }}
        customerID={''} 
      />
    }
  />
</Route>
ymonye commented 1 year ago

Hey @dbritto-dev, thanks a ton! Everything loads perfectly now :) Cheers

dbritto-dev commented 1 year ago

@aorait hope this works for you as well

aorait commented 1 year ago

@dbritto-dev I haven't gotten a chance to try this since I have moved away from this project. I am marking this as closed since the solution you have provided does make sense.