在我的Next.js应用程序中,我似乎无法访问窗口:

未处理的拒绝(ReferenceError):没有定义窗口

componentWillMount() {
    console.log('window.innerHeight', window.innerHeight);
}


当前回答

将代码从componentWillMount()移动到componentDidMount():

componentDidMount() {
  console.log('window.innerHeight', window.innerHeight);
}

在Next.js中,componentDidMount()只在提供窗口和其他浏览器特定api的客户端上执行。来自Next.js wiki:

js是通用的,这意味着它首先在服务器端执行代码, 然后客户端。窗口对象只在客户端显示,因此if 你绝对需要在一些React组件中访问它 应该把该代码放在componentDidMount中。这个生命周期方法 只能在客户端执行。你可能还想检查一下是否有 是不是有其他的通用库可以满足你的需要。

同样,componentWillMount()将在React的v17中被弃用,因此在不久的将来使用它实际上可能是不安全的。

其他回答

您可以定义一个状态变量并使用窗口事件句柄来处理这样的更改。

const [height, setHeight] = useState();

useEffect(() => {
    if (!height) setHeight(window.innerHeight - 140);
    window.addEventListener("resize", () => {
        setHeight(window.innerHeight - 140);
    });
}, []);

我想把我觉得有趣的方法留给未来的研究人员。它使用了一个自定义钩子useEventListener,可以用于许多其他需求。

请注意,您需要对最初发布的内容进行一些更改,就像我在这里建议的那样。

所以它会像这样结束:

import { useRef, useEffect } from 'react'

export const useEventListener = (eventName, handler, element) => {
  const savedHandler = useRef()

  useEffect(() => {
    savedHandler.current = handler
  }, [handler])

  useEffect(() => {
    element = !element ? window : element
    const isSupported = element && element.addEventListener
    if (!isSupported) return

    const eventListener = (event) => savedHandler.current(event)

    element.addEventListener(eventName, eventListener)

    return () => {
      element.removeEventListener(eventName, eventListener)
    }
  }, [eventName, element])
}

日期:06/08/2021

检查窗口对象是否存在,然后跟随代码进行操作。

 function getSelectedAddress() {
    if (typeof window === 'undefined') return;

    // Some other logic
 }

对于这种情况,Next.js具有动态导入功能。

对于包含只在浏览器中工作的库的模块,建议使用动态导入。请参考

这是我做过的一个简单的解决方法。

const runOnClient = (func: () => any) => {
  if (typeof window !== "undefined") {
    if (window.document.readyState == "loading") {
      window.addEventListener("load", func);
    } else {
      func();
    }
  }
};

用法:

runOnClient(() => {
// access window as you like
})

// or async
runOnClient(async () => {
// remember to catch errors that might be raised in promises, and use the `await` keyword wherever needed
})

这比typeof window !== "undefined"要好,因为如果你只是检查窗口不是undefined,如果你的页面被重定向到,它不会工作,它只在加载时工作一次。但是,即使页面被重定向到,这个解决方法也可以工作,而不仅仅是在加载时一次。