skip to Main Content
"use client";
import { useEffect, useState } from "react";

const useWindowWidth = (delay = 100): number => {
  const [windowWidth, setWindowWidth] = useState(window.innerWidth);

  useEffect(() => {
    ...
  }, []);

  return windowWidth;
};

export default useWindowWidth;

Why does this hook run on the server if "use client" is added? It doesn’t cause the application to crash, everything works as the error doesn’t exist, it just logs the error mentioned in the title at the const [windowWidth, setWindowWidth] = useState(window.innerWidth); line on the window object.

This is from the official Next.js docs:

Using Client Components in Next.js

To use Client Components, you can
add the React "use client" directive at the top of a file, above your
imports.

"use client" is used to declare a boundary between a Server and Client
Component modules. This means that by defining a "use client" in a
file, all other modules imported into it, including child components,
are considered part of the client bundle – and will be rendered by
React on the client.

2

Answers


  1. According to this discussion, the "use client" only means that it also runs on the client. You can use useEffect to access the window object without any errors.

    Login or Signup to reply.
  2. Client components will run in the client BUT will be rendered firstly in the server.

    What does that mean?

    The component with "use client" directive is running in the browser and able to use client APIs like window. But, at the first render, It’ll be executed in the server without interactivity to make it render fast.

    What is the problem with your component?

    You initialized useState with window.innerWidth which is not accessible in the server so, you will get an error saying cannot read property of undefined. reading window.

    How to fix it?

    1. Use the window within use(Layout)Effect. the useEffect hook with empty dependency array delays the callback function until the first render is completed.

    2. Use client-only in your component so it won’t be rendered in the server anymore:

    npm install client-only
    
    "use client"
    
    import "client-only"
    
    export ...
    

    This trick is straightforward. It just throws an error on the server so It will redirect it to the client boundary.

    1. Dynamic import
    // page.tsx
    import dynamic from 'next/dynamic'
    
    const ClientComponent = dynamic(() => import("path/to/your/client/component"), {ssr: false})
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search