简体   繁体   中英

NextJS: How do I get this component to display width on page load?

When running the below code that gets the screen width of the browser I get this error:

ReferenceError: window is not defined

The code commented-out works, uses 0 as a default, but correctly updates when the browser width is changed.

I either get the window is not defined error or pass a default number to state, which displays the incorrect width on page load.

How do I define window.innerWidth at page load?

import React, { useState, useEffect } from "react";

const WindowTracker = () => {
    const [show, setShow] = useState(true);
    // const [windowWidth, setWindowWidth] = useState(0);
    const [windowWidth, setWindowWidth] = useState(window.innerWidth);

    const triggerToggle = () => {
        setShow(!show);
    };

    useEffect(() => {
        function watchWidth() {
            setWindowWidth(window.innerWidth);
        }

        window.addEventListener("resize", watchWidth);

        return function () {
            window.removeEventListener("resize", watchWidth);
        };
    }, []);

    return (
        <div>
            <button onClick={triggerToggle}>Toggle WindowTracker</button>
            {show && <h1>Window width: {windowWidth}px</h1>}
        </div>
    );
    // }
};

export default WindowTracker;

Thanks!

Use this Hook:

 const [windowWidth, setWindowWidth] = useState(); useEffect(() => { setWindowWidth(window.innerWidth) }, [window.innerWidth])

This happens because in the pre rendering that nextjs performs on the window server it is not yet defined, I solved this in my code by adding an if, this is an example code of how it would look

import React, { useState, useEffect } from "react";

const WindowTracker = () => {
  const [show, setShow] = useState(true);
  // const [windowWidth, setWindowWidth] = useState(0);
  const [windowWidth, setWindowWidth] = useState(typeof window !== "undefined" ? window.innerWidth : 0);

  const triggerToggle = () => {
    setShow(!show);
  };

  useEffect(() => {
    if (typeof window !== "undefined") {
      function watchWidth() {
        setWindowWidth(window.innerWidth);
      }

      window.addEventListener("resize", watchWidth);

      return function () {
        window.removeEventListener("resize", watchWidth);
      };
    }
  }, []);

  return (
    <div>
      <button onClick={triggerToggle}>Toggle WindowTracker</button>
      {show && <h1>Window width: {windowWidth}px</h1>}
    </div>
  );
  // }
};

export default WindowTracker;

You should trigger setWindowWidth when component did mount

const isClientSide = () => typeof window !== 'undefined';

const getWindowSize = () => {
    if (isClientSide()) return window.innerWidth
    return 0
}

const WindowTracker = () => {
    const [show, setShow] = useState(true);
    const [windowWidth, setWindowWidth] = useState(getWindowSize());

    const triggerToggle = () => {
        setShow(!show);
    };

    useEffect(() => {
        function watchWidth() {
            setWindowWidth(window.innerWidth);
        }

        window.addEventListener("resize", watchWidth);
        setWindowSize(getWindowSize());  <=== This should set the right width
        return function () {
            window.removeEventListener("resize", watchWidth);
        };
    }, []);

    return (
        <div>
            <button onClick={triggerToggle}>Toggle WindowTracker</button>
            {show && <h1>Window width: {windowWidth}px</h1>}
        </div>
    );
};

export default WindowTracker;

Inside useEffect hook you can also invoke setWindowWidth(window.innerWidth); at to set the state with window.innerWidth to have desired width on pageLoad.

const [windowWidth, setWindowWidth] = useState(0);

useEffect(() => {
        function watchWidth() {
            setWindowWidth(window.innerWidth);
        }

        window.addEventListener("resize", watchWidth);

        //  Call right away so state gets updated with initial window size
        setWindowWidth(window.innerWidth);

        return function () {
            window.removeEventListener("resize", watchWidth);
        };
    }, []);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM