I am learning ReactJS so I am completely new at this.
I created an authentication/authorization service that I know works in React just fine. What I am trying to do is protect the primary application with a login. As I understand, I want a high-order component such as this in order to protect the core of the application:
const withAuth = (Component) => {
const AuthenticatedComponent = () => {
const isAuthenticated = MyService.isUserAuthenticated();
if (!isAuthenticated) {
return <Navigate to="/login" />;
}
return <Component />;
};
return AuthenticatedComponent;
};
export default withAuth;
I have two components that are pretty simple to test the theory that are both very similar. Essentially they look like this:
export default function DefaultLandingPage() {
return(
<>
<div>
This would be the dashboard page after login.
</div>
</>
);
}
export default function LoginPage() {
return(
<>
<div>
This is where the user would log in.
</div>
</>
);
}
I tried to use these in my App.js
file.
First I tried this:
function App() {
return (
<>
<Routes>
<Route path="/" exact component={withAuth(DefaultLandingPage) } />
<Route path="/login" element={ <LoginPage /> } />
</Routes>
</>
);
}
That results in:
Matched leaf route at location "/" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.
I tried changing it to:
<Route path="/" exact element={ withAuth(DefaultLandingPage) } />
Which results in:
Warning: Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.
Can someone point me in the proper direction?
I did find this post and am headed down that route right now; however, I am not sure what my incorrect logic is here.
Can someone explain why my logic doesn't work here?
What concerns me, is that I want to also protect the pages with fine-grained privileges and was hoping to create something that would function like this:
<Route path="/" exact element={ withAuth(DefaultLandingPage) } />
<Route path="/some-sub-area" element={ withAuth(withPermission(SomeSubArea, 'permission-xyz')) } />
For your first case, make sure your prop component
is capitalized to Component
per the router documentation. For your second issue, your withAuth
function returns a function reference to AuthenticatedComponent
rather than treating it as a functional component. Opting to return <AuthenticatedComponent/>
should send you in the right direction!