0

Trying to implement private ( authenticated ) routes in Nextjs using HOC and cookies but running into error below:

TypeError: Object(...) is not a function
at export default withPrivateRoute(Private);

I have checked elsewhere in the app that cookies are available and also sent with the request. They seem to be available server side.

The HOC at `/components/withPrivateRoute

import { withRouter } from 'next/router';
import { withCookies } from 'react-cookie';

const withPrivateRoute = (authComponent) => {
return class Private extends React.Component {
    componentDidMount() {
        console.log('PRIVATE ROUTE', this.props);
        const { router, cookies } = this.props;
        const intendedRoute = router.pathname;
        const isAdmin = !!cookies.get('isAdmin');
        const isAuthenticated = !!cookies.get('username');
        if (!isAuthenticated) {
            router.push({
                pathname: '/login',
                query: { from: intendedRoute },
            });
        }
        if (
            isAuthenticated &&
            router.pathname.includes('admin') &&
            !isAdmin
        ) {
            router.push('/');
        }
    }

    render() {
        // eslint-disable-next-line react/jsx-props-no-spreading
        return <authComponent {...this.props} />;
    }
}
}

export default withCookies(withRouter(withPrivateRoute));

The private route example:

import withPrivateRoute from '../components/withPrivateRoute';
import getCategories from '../lib/getCategories';

const Private = (props) => {
  console.log('props', props);
  return <div>Private route </div>;

}

export default withPrivateRoute(Private);

export async function getStaticProps() {
  let categories = await getCategories();
  categories = categories.data.categories;
 return {
    props: {
        categories,
    },
 };
 }
BernardA
  • 1,391
  • 19
  • 48

1 Answers1

-2

I have since found a better way to handle private routes in Nextjs from this discussion:

Everything is handled inside getServerSideProps, no HOC required.

 class Private extends React.Component{
  render() {
    console.log('props', this.props);
    return <p>Private route</p>;
  }
}

 export default Private;

export async function getServerSideProps(context) {
const { req: { headers, url }, res } = context;
const cookies = {};
if (headers && headers.cookie) {
    headers.cookie.split(';').forEach((cookie) => {
        const parts = cookie.match(/(.*?)=(.*)$/);
        cookies[parts[1].trim()] = (parts[2] || '').trim();
    });
}
const isAuthenticated = !!cookies.username;
const isAdmin = !!cookies.isAdmin;
if (!isAuthenticated) {
    res.setHeader('Location', `/login?from=${url}`);
    res.statusCode = 307;
}
if (
    isAuthenticated &&
    url.includes('admin') &&
    !isAdmin
) {
    res.setHeader('Location', '/');
    res.statusCode = 307;
}
return {
    props: {
    },
};
}
BernardA
  • 1,391
  • 19
  • 48