NextJS | Typescript issue when i import my protected auth to page

77 views Asked by At
this my protected.tsx,when i one use this on page below,some error comes like 

Server Error

Error: Attempted to call the default export of C:\Importir.id\NextJs\diecast-app\app\hoc\withProtected.tsx from the server but it's on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.

'use client';
import React from 'react';
import { useUser } from '../context/user';
import { useRouter } from 'next/navigation';

interface ProtectedProps {}

const withProtected = (WrappedComponent: React.ComponentType<ProtectedProps>) => {
  const WithProtected: React.FC<ProtectedProps> = (props) => {
    const router = useRouter();
    const user = useUser();
    const { uid } = user;

    if (typeof window === 'undefined') {
      return null;
    }

    console.log({ uid });

    if (!uid) {
      router.replace('/');
      return <></>;
    }

    return <WrappedComponent {...props} />;
  };

  return WithProtected;
};

export default withProtected;

and this page code thats have error

import React from 'react';
import withProtected from '../hoc/withProtected';

const StorePage: React.FC = () => {
  return (
    <div>
      <h2>Halaman diecast</h2>
    </div>
  );
};

export default withProtected(StorePage);

please solve my problem,i really say thankyou for you all

2

There are 2 answers

2
Hashan Hemachandra On

The error is due to an attempt to use a client-side function on the server-side in a Next.js application. The withProtected higher-order component (HOC) you've created is designed to work on the client-side, but Next.js tries to execute it on the server during server-side rendering (SSR), which leads to the error.

  1. Use useEffect for Client-Side Operations: Since you're dealing with authentication and routing, which are inherently client-side operations, you should perform these inside a useEffect hook. This will ensure they are only executed on the client-side after the component has mounted.

  2. Return a Placeholder on the Server-Side: During the server-side rendering, return a placeholder (like null or a loading component) until the client-side script takes over.

  3. Redirect on the Client-Side: Perform the redirection using useRouter inside the useEffect hook.

Try this way -

withProtected.tsx:

'use client';
import React, { useEffect } from 'react';
import { useUser } from '../context/user';
import { useRouter } from 'next/router';

interface ProtectedProps {}

const withProtected = (WrappedComponent: React.ComponentType<ProtectedProps>) => {
  const WithProtected: React.FC<ProtectedProps> = (props) => {
    const router = useRouter();
    const user = useUser();

    useEffect(() => {
      if (!user.uid) {
        router.replace('/');
      }
    }, [user, router]);

    // Return null or a loading component on the server
    if (typeof window === 'undefined' || !user.uid) {
      return null;
    }

    return <WrappedComponent {...props} />;
  };

  return WithProtected;
};

export default withProtected;

page component (StorePage) remains the same:

import React from 'react';
import withProtected from '../hoc/withProtected';

const StorePage: React.FC = () => {
  return (
    <div>
      <h2>Halaman diecast</h2>
    </div>
  );
};

export default withProtected(StorePage);
1
오병문 On

You are importing useRouter from the wrong package. useRouter should be taken from next/router, but according to the error message it tried to be taken from next/navigation

import { useRouter } from 'next/router';

Additionally, the withProtected higher-order component (HOC) cannot check the user's login status during SSR (server-side rendering), so it must be executed only on the client side.