7

I am trying to implement a protected route to only allow logged in users to access my app. The code I have written seems to work, I am redirected to my login page when I try to access the homepage without being logged in, however once I am logged in I can access the page but I does not render and I get the following error: Click here for error

I have tried multiple methods and wrapping the element in my protected route seems like the V6 way of doing things, however it doesn't seem to work for me:

My protected route

interface PrivateRouteProps extends RouteProps {
}

const PrivateRoute: React.FC<PrivateRouteProps> = ({...rest}) => {
    const auth = useAuth();

    if (auth?.user === null) {
        return <Navigate to='/'/>;
    }
    return <Route {...rest}/>;
};

export default PrivateRoute;

My app (route usage)

function App() {
    useEffect(() => {
      API
        .get('api', '/reservation', {})
        .then(response => {
          console.log(response);
        })
        .catch(error => {
          console.log(error.response);
        });

    }, [])
    return (
      <Router>
        <Routes>
          <Route path='/' element={<LoginPage />}/>
          <Route path='/consultAndReserve' element={<PrivateRoute><Navbar/><ConsultReserve/></PrivateRoute>} />
          <Route path='/consultAndReserve/:date' element={<><Navbar/><ConsultReserveWithDate/></>}/>
          <Route path='/myReservations'  element={<><Navbar/><Reservations/></>}/>
          <Route path='/tracing'  element={<><Navbar/><Tracing/></>}/>
        </Routes>
      </Router>
  );
}

What am I doing wrong?

2
  • Instead of images of your code you should include them in your question as properly formatted and readable code snippets. Commented Mar 15, 2022 at 20:01
  • @DrewReese Thank you for your suggestion, I have modified my question. Commented Mar 15, 2022 at 20:19

1 Answer 1

11

It's fairly trivial to create a "PrivateRoute" component, even in TypeScript.

In your case you can't directly render a Route component as the error points out. This was a breaking change between RRDv5 and RRDv6. You can render the children prop since you are directly wrapping the components you want to protect.

Example:

const PrivateWrapper = ({ children }: { children: JSX.Element }) => {
  const auth = useAuth();
  return auth?.user ? children : <Navigate to="/" replace />;
};

Usage:

<Routes>
  ...
  <Route
    path="/consoleAndReserve"
    element={(
      <PrivateWrapper>
        <Navbar />
        <ConsultReserve />
      </PrivateWrapper>
    )}
  />
  ...
</Routes>
Sign up to request clarification or add additional context in comments.

7 Comments

I think I understand what my issue is. The problem is that I am trying to render a Route with my PrivateRoute, which I am not allowed to do. With your method, I would only redirect the user to said page using Navigate instead of a Route? I tried applying your code to mine and I get the following line: JSX element type 'PrivateWrapper' does not have any construct or call signatures.
@ginoboy Ok, so this is where my minimal experience with Typescript shows through. Let me play around to see if I can get a correct typing for this.
@ginoboy React.FC<any> is very general, but works for a general auth wrapper.
const PrivateWrapper = ({ children }: { children: JSX.Element }) => { should do it. That requires that children is a JSX.Element (more specific than ReactNode). You need that type in order to return children directly because a component can only return JSX.Element | null.
Drew's revised answer did the trick for me. What is the advantage of using JSX.Element over ReactNode?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.