在NextJS React应用中未定义窗口?

时间:2019-03-13 20:53:55

标签: javascript reactjs next.js

在我的 NextJS 应用中,我似乎无法访问window

  

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

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

enter image description here

11 个答案:

答案 0 :(得分:8)

将代码从componentWillMount()移至componentDidMount()

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

在NextJS中,componentDidMount()仅在window和其他特定于浏览器的API可用的客户端上执行。来自NextJS wiki

  

Next.js是通用的,这意味着它首先在服务器端执行代码,   然后是客户端。窗口对象仅存在于客户端,因此如果   您绝对需要在某些React组件中访问它,您   应该将该代码放在componentDidMount中。此生命周期方法将   仅在客户端上执行。您可能还需要检查是否   不是满足您需求的替代通用库。

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

答案 1 :(得分:3)

没有SSR

enter image description here

import dynamic from 'next/dynamic'

const DynamicComponentWithNoSSR = dynamic(
  () => import('../components/hello3'),
  { ssr: false }
)

function Home() {
  return (
    <div>
      <Header />
      <DynamicComponentWithNoSSR />
      <p>HOME PAGE is here!</p>
    </div>
  )
}

export default Home

答案 2 :(得分:3)

我必须从 URL 访问哈希,所以我想出了这个

const hash = global.window && window.location.hash;

答案 3 :(得分:1)

componentWillMount()生命周期挂钩既可以在服务器上也可以在客户端上使用。如果您的服务器在页面投放期间不知道“窗口”或“文档”,建议将代码移至

解决方案1:

componentDidMount()</code>.

或者,解决方案2

如果这只是您要执行的操作,则可以编写如下内容:

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

答案 4 :(得分:1)

其他解决方案是使用process.browser仅在客户端渲染期间执行命令。

if (process.browser) {
  // client-side-only code
}

答案 5 :(得分:1)

对于这种情况,Next.js 有 Dynamic Import

包含仅在浏览器中工作的库的模块,建议使用动态导入。 Refer

答案 6 :(得分:0)

在类组件的构造函数中,您可以添加

    if (typeof window === 'undefined') {
        global.window = {}
    }

示例:

import React, { Component } from 'react'

class MyClassName extends Component {

constructor(props){
    super(props)
    ...
    if (typeof window === 'undefined') {
        global.window = {}
    }

}

这将避免该错误(在我的情况下,该错误将在单击页面的重新加载后发生)

答案 7 :(得分:0)

如果您使用反应钩,则可以将代码移至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

答案 8 :(得分:0)

当我在next.js中开发Web应用程序时遇到了同样的问题。这解决了我的问题,您必须在生命周期方法或React Hook中引用窗口对象。例如,假设我想用redux创建一个存储变量,并且在这个存储中我想使用Windows对象,我可以按照以下步骤进行操作:

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

因此,基本上,当您使用窗口的对象时,请始终使用钩子或componentDidMount()生命周期方法进行播放

答案 9 :(得分:0)

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

您可以创建一个非常有用的钩子来获取动态 window.innerHeightwindow.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();

答案 10 :(得分:0)

日期:06/08/2021

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

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

    // Some other logic
 }