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

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

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


当前回答

componentWillMount()生命周期钩子在服务器端和客户端都可以工作。在您的情况下,服务器在页面服务期间不知道窗口或文档,建议将代码移动到任何一个

解决方案1:

componentDidMount()

或者,方案2

如果它是你只想执行的东西,那么你可以这样写:

componentWillMount() {
    if (typeof window !== 'undefined') {
        console.log('window.innerHeight', window.innerHeight);
    }
}

其他回答

发生错误是因为窗口尚未可用,而组件仍在挂载。组件挂载后,可以访问窗口对象。

您可以创建一个非常有用的钩子来获取动态窗口。innerHeight或window.innerWidth

const useDeviceSize = () => {

  const [width, setWidth] = useState(0)
  const [height, setHeight] = useState(0)

  const handleWindowResize = () => {
    setWidth(window.innerWidth);
    setHeight(window.innerHeight);
  }

  useEffect(() => {
    // component is mounted and window is available
    handleWindowResize();
    window.addEventListener('resize', handleWindowResize);
    // unsubscribe from the event on component unmount
    return () => window.removeEventListener('resize', handleWindowResize);
  }, []);

  return [width, height]

}

export default useDeviceSize 

用例:

const [width, height] = useDeviceSize();

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

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

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

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

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

有史以来最好的解决方案 从'next/dynamic'导入dynamic; const Chart = dynamic(()=> import('react-apexcharts'), { ssr:假的, })

当我在next.js中开发web应用程序时,我也面临着同样的问题,这解决了我的问题,你必须在生命周期方法或react Hook中引用引用窗口对象。例如,假设我想用redux创建一个存储变量,在这个存储中我想使用一个windows对象,我可以这样做:

let store
useEffect(()=>{
    store = createStore(rootReducers,   window.__REDUX_DEVTOOLS_EXTENSION__ && 
    window.__REDUX_DEVTOOLS_EXTENSION__())
 }, [])
 ....

所以基本上,当你使用window的对象时,总是使用钩子来玩或者componentDidMount()生命周期方法

如果你使用React Hooks,你可以将代码移动到Effect Hook中:

import * as React from "react";

export const MyComp = () => {

  React.useEffect(() => {
    // window is accessible here.
    console.log("window.innerHeight", window.innerHeight);
  }, []);

  return (<div></div>)
}

useEffect中的代码只在客户端(在浏览器中)执行,因此它可以访问window。