Nextjs useRouter issue in ^14.0.4

123 Views Asked by At

I am importing useRouter from "next/navigation" in a Higher Order Component (HOC). It is throwing the below error/issue:

node_modules/next/dist/client/components/app-router.js

ReferenceError: location is not defined

I'm using app router. The HOC uses by some wrapper components.

The component that call uses the HOC:

const AccountsTypesWrapper = () => {
  const dispatch = useDispatch();
  return (
    <>
      <SubHeader
        pageLink={pageLinks.account.subMenu}
        title="Accounts"
        form={{ label: "Add Account Types" }}
        createPermission={Permissions.ACCOUNT_TYPE_CREATE}
        formHandler={() =>
          dispatch(
            accountsAction.onAction({
              key: AccountsModuleItems.ACCOUNT_TYPES,
              actionType: "CREATE",
            })
          )
        }
      />

      <NestedHeader
        links={pageLinks.account.nestedMenu.accounts}
        label="Accounts"
      />

      <AccountsTypesModals />
      <AccountTypesTable />
    </>
  );
};

export default withPermission(
  AccountsTypesWrapper,
  Permissions.ACCOUNT_TYPE_READ
);

The HOC:

const withPermission = (
  WrappedComponent: React.ComponentType<any>,
  requiredPermission: Permissions
) => {
  const WithPermission: React.FC<any> = (props) => {
    const router = useRouter();
    const hasPermission = usePermissionCheck(requiredPermission);

    if (!hasPermission) {
      router.push("/");
    }

    return hasPermission ? (
      <WrappedComponent {...props} />
    ) : (
      <Loading isFullSize={true} />
    );
  };

  return WithPermission;
};

export default withPermission;
2

There are 2 best solutions below

2
Sudip Shrestha On BEST ANSWER

Add 'use client' at the top of your file to mark the current module and its transitive dependencies as client code.

'use client'

import { useRouter } from 'next/navigation'

const withPermission = (
  WrappedComponent: React.ComponentType<any>,
  requiredPermission: Permissions
) => {
  const WithPermission: React.FC<any> = (props) => {
    const router = useRouter();
    const hasPermission = usePermissionCheck(requiredPermission);

    React.useEffect(() => {
      if (!hasPermission) {
        router.push("/");
      }
    }, [hasPermission, router]);

    return hasPermission ? (
      <WrappedComponent {...props} />
    ) : (
      <Loading isFullSize={true} />
    );
  };

  return WithPermission;
};

export default withPermission;
2
sundaycode On

It sounds like you are using the Pages Router. The useRouter from next/navigation is for the App Router.

I think what you are looking for is:

import { useRouter } from 'next/router'