skip to Main Content

Im getting several errors like this error in my nextjs App. Here is a simple example. How can i refactor this so that there are no hydration errors? Are there tricks (way of thinking) for getting better at this in the future?

Error

Warning: Text content did not match. Server: "Checking your credentials…" Client: "Profile" Error Component Stack

Nav.tsx

'use client';
import { auth } from '@/firebase/firebase.config';
import Link from 'next/link';
import { useAuthState } from 'react-firebase-hooks/auth';

export const AuthNav = () => {
  const [user, loading] = useAuthState(auth);

  if (loading) return <div>
    <Link href="">Checking your credentials...</Link>
  </div>;

  return (
    <div>
      {user && <Link href="">Profile</Link>}
      {!user && <Link href="">Sign In</Link>}
    </div>
  );
};

versions

    "@nrwl/node": "^19.8.4",
    "@vitejs/plugin-react": "^4.3.3",
    "axios": "^1.6.0",
    "colors": "^1.4.0",
    "cors": "^2.8.5",
    "express": "^4.18.1",
    "next": "14.2.16",
    "react": "18.3.1",
    "react-dom": "18.3.1",
    "react-icons": "^5.3.0",
    "react-router-dom": "6.11.2",
    "tslib": "^2.3.0"

2

Answers


  1. The default is server component in Next.js AppRouter, so that’s rendered in server and then it’s rendered in client side. I expect loading is null or undefined in server at first and then it would be true or false.

    To avoid this you need to use cookie for authenticated variable because cookie is available to access in both of server and client.

    Login or Signup to reply.
  2. From the nextjs documentation, I see 2 solutions :

    1. Using an effect
    export const AuthNav = () => {
      const [user, loading] = useAuthState(auth);
      const [isFirst, setIsFirst] = useState(true);
    
      useEffect(() => {
        setIsFirst(false);
      }, []);
    
      if (firstRender || loading)  {
        return (
          <div>
            <Link href="">Checking your credentials...</Link>
          </div>
        );
      }
      
      return (
        <div>
          {user && <Link href="">Profile</Link>}
          {!user && <Link href="">Sign In</Link>}
        </div>
      );
    };
    
    1. Disabling ssr for the AuthNav component
    import dynamic from 'next/dynamic';
    
    const AuthNav = dynamic(
      () => import('./AuthNav').then(m => m.AuthNav),
      { ssr: false }
    );
    
    export default function Page() {
      return (
        <div>
          <AuthNav />
        </div>
      )
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search