I am trying to implement a privateRoute component in NextJS without server side rendering and I am a bit stuck at the moment as it is slightly different to how I have rendered this before in ReactJS. I have tried to implement an auth HOC which wraps components in the default export but I cannot get the child components of the wrapped element to display.
Here is my withAuth HOC that wraps components that are to be checked for auth:
/* eslint-disable react-hooks/exhaustive-deps */
import { useRouter } from 'next/router';
import React, { useEffect } from 'react';
import { useSelector } from 'react-redux';
import Login from '../pages/login';
import { getAuthState, LoginStatusEnum } from '../store/slices/authSlice.store';
const withAuth = (Component: React.FC) => {
const AuthenticatedComponent = (props: any) => {
const router = useRouter();
const { loggedStatus } = useSelector(getAuthState);
// TODO token auth needs to be added
useEffect(() => {
// If user is not logged in, return login component
if (loggedStatus !== LoginStatusEnum.LOGGED_IN) {
router.push('/login');
}
}, [loggedStatus]);
// If user is logged in, return original component
return <Component {...props} />;
};
return AuthenticatedComponent;
};
export default withAuth;
And example of a component being wrapped by this auth HOC, the dashboard.
import Head from 'next/head';
import withAuth from '../components/PrivateRoute';
import getLayout, { LayoutOptions } from '../utils/getLayout/getLayout.util';
import { NextPageWithLayout } from './_app';
const Dashboard: NextPageWithLayout = ({ ...props }) => {
return (
<>
<Head>
<title>Everyone Active - Dashboard</title>
</Head>
<div>Welcome to the dashboard</div>
</>
);
};
Dashboard.getLayout = getLayout(LayoutOptions.STANDARD);
Dashboard.defaultProps = {};
Dashboard.propTypes = {};
export default withAuth(Dashboard);
This works when I login and go to the dashboard but the only component that shows in the browser is the dashbaord component. It does not pick up the selected layout component that are set in the Dashboard component getLayout(LayoutOptions.STANDARD)
Here is my layout helper:
const getLayout = (name: LayoutOptions) => {
// eslint-disable-next-line react/display-name
return (page: ReactElement) => {
switch (name) {
case LayoutOptions.STANDARD:
return <StandardLayout>{page}</StandardLayout>;
case LayoutOptions.FULL_WIDTH:
return <FullWidthLayout>{page}</FullWidthLayout>;
default:
throw new Error(`Layout "${name}" does not exist.`);
}
};
};
export default getLayout;
And the layout component:
const StandardLayout: React.FC<PropsWithChildren<StandardLayoutProps>> = ({ children, ...props }) => {
return (
<div className="flex flex-col h-screen justify-between">
<div>
<Header />
<div className="mt-4 container grid md:grid-cols-12 mx-auto">
<aside className="col-span-3 order-2 md:order-1">Sidebar</aside>
<main className="col-span-9 order-1 md:order-2">{children}</main>
</div>
</div>
<Footer />
</div>
);
};
StandardLayout.defaultProps = {};
StandardLayout.propTypes = {};
export default StandardLayout;
When I remove the withAuth HOC wrapper from the Dashboard component all of the layout is pulled through. Can anyone see where I am going wrong here?